summaryrefslogtreecommitdiff
path: root/chromium/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.cc')
-rw-r--r--chromium/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.cc205
1 files changed, 205 insertions, 0 deletions
diff --git a/chromium/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.cc b/chromium/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.cc
new file mode 100644
index 00000000000..8143512f325
--- /dev/null
+++ b/chromium/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.cc
@@ -0,0 +1,205 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.h"
+
+#include "base/bind.h"
+#include "content/public/browser/browser_context.h"
+#include "extensions/browser/api/display_source/display_source_connection_delegate_factory.h"
+
+namespace {
+const char kErrorCannotHaveMultipleSessions[] =
+ "Multiple Wi-Fi Display sessions are not supported";
+const char kErrorSinkNotAvailable[] = "The sink is not available";
+} // namespace
+
+namespace extensions {
+
+using namespace api::display_source;
+
+WiFiDisplaySessionServiceImpl::WiFiDisplaySessionServiceImpl(
+ DisplaySourceConnectionDelegate* delegate,
+ mojo::InterfaceRequest<WiFiDisplaySessionService> request)
+ : binding_(this, std::move(request)),
+ delegate_(delegate),
+ sink_state_(SINK_STATE_NONE),
+ sink_id_(DisplaySourceConnectionDelegate::kInvalidSinkId),
+ weak_factory_(this) {
+ delegate_->AddObserver(this);
+}
+
+WiFiDisplaySessionServiceImpl::~WiFiDisplaySessionServiceImpl() {
+ delegate_->RemoveObserver(this);
+ Disconnect();
+}
+
+// static
+void WiFiDisplaySessionServiceImpl::BindToRequest(
+ content::BrowserContext* browser_context,
+ mojo::InterfaceRequest<WiFiDisplaySessionService> request) {
+ DisplaySourceConnectionDelegate* delegate =
+ DisplaySourceConnectionDelegateFactory::GetForBrowserContext(
+ browser_context);
+ CHECK(delegate);
+
+ new WiFiDisplaySessionServiceImpl(delegate, std::move(request));
+}
+
+void WiFiDisplaySessionServiceImpl::SetClient(
+ WiFiDisplaySessionServiceClientPtr client) {
+ DCHECK(client);
+ DCHECK(!client_);
+ client_ = std::move(client);
+ client_.set_connection_error_handler(
+ base::Bind(&WiFiDisplaySessionServiceImpl::OnClientConnectionError,
+ weak_factory_.GetWeakPtr()));
+}
+
+void WiFiDisplaySessionServiceImpl::Connect(int32_t sink_id,
+ int32_t auth_method,
+ const mojo::String& auth_data) {
+ DCHECK(client_);
+ // We support only one Wi-Fi Display session at a time.
+ if (delegate_->connection()) {
+ client_->OnConnectRequestHandled(false, kErrorCannotHaveMultipleSessions);
+ return;
+ }
+
+ const DisplaySourceSinkInfoList& sinks = delegate_->last_found_sinks();
+ auto found = std::find_if(sinks.begin(), sinks.end(),
+ [sink_id](const DisplaySourceSinkInfo& sink) {
+ return sink.id == sink_id;
+ });
+ if (found == sinks.end() || found->state != SINK_STATE_DISCONNECTED) {
+ client_->OnConnectRequestHandled(false, kErrorSinkNotAvailable);
+ return;
+ }
+ AuthenticationInfo auth_info;
+ if (auth_method != AUTHENTICATION_METHOD_NONE) {
+ DCHECK(auth_method <= AUTHENTICATION_METHOD_LAST);
+ auth_info.method = static_cast<AuthenticationMethod>(auth_method);
+ auth_info.data = scoped_ptr<std::string>(new std::string(auth_data));
+ }
+ auto on_error = base::Bind(&WiFiDisplaySessionServiceImpl::OnConnectFailed,
+ weak_factory_.GetWeakPtr(), sink_id);
+ delegate_->Connect(sink_id, auth_info, on_error);
+ sink_id_ = sink_id;
+ sink_state_ = found->state;
+ DCHECK(sink_state_ == SINK_STATE_CONNECTING);
+ client_->OnConnectRequestHandled(true, "");
+}
+
+void WiFiDisplaySessionServiceImpl::Disconnect() {
+ if (sink_id_ == DisplaySourceConnectionDelegate::kInvalidSinkId) {
+ // The connection might drop before this call has arrived.
+ // Renderer should have been notified already.
+ return;
+ }
+
+ const DisplaySourceSinkInfoList& sinks = delegate_->last_found_sinks();
+ auto found = std::find_if(sinks.begin(), sinks.end(),
+ [this](const DisplaySourceSinkInfo& sink) {
+ return sink.id == sink_id_;
+ });
+ DCHECK(found != sinks.end());
+ DCHECK(found->state == SINK_STATE_CONNECTED ||
+ found->state == SINK_STATE_CONNECTING);
+
+ auto on_error = base::Bind(&WiFiDisplaySessionServiceImpl::OnDisconnectFailed,
+ weak_factory_.GetWeakPtr(), sink_id_);
+ delegate_->Disconnect(on_error);
+}
+
+void WiFiDisplaySessionServiceImpl::SendMessage(const mojo::String& message) {
+ if (sink_id_ == DisplaySourceConnectionDelegate::kInvalidSinkId) {
+ // The connection might drop before this call has arrived.
+ return;
+ }
+ auto connection = delegate_->connection();
+ DCHECK(connection);
+ DCHECK_EQ(sink_id_, connection->GetConnectedSink().id);
+ connection->SendMessage(message);
+}
+
+void WiFiDisplaySessionServiceImpl::OnSinkMessage(const std::string& message) {
+ DCHECK(delegate_->connection());
+ DCHECK_NE(sink_id_, DisplaySourceConnectionDelegate::kInvalidSinkId);
+ DCHECK(client_);
+ client_->OnMessage(message);
+}
+
+void WiFiDisplaySessionServiceImpl::OnSinksUpdated(
+ const DisplaySourceSinkInfoList& sinks) {
+ if (sink_id_ == DisplaySourceConnectionDelegate::kInvalidSinkId)
+ return;
+ // The initialized sink id means that the client should have
+ // been initialized as well.
+ DCHECK(client_);
+ auto found = std::find_if(sinks.begin(), sinks.end(),
+ [this](const DisplaySourceSinkInfo& sink) {
+ return sink.id == sink_id_;
+ });
+ if (found == sinks.end()) {
+ client_->OnError(ERROR_TYPE_CONNECTION_ERROR, "The sink has disappeared");
+ client_->OnTerminated();
+ sink_id_ = DisplaySourceConnectionDelegate::kInvalidSinkId;
+ }
+
+ SinkState actual_state = found->state;
+
+ if (actual_state == sink_state_)
+ return;
+
+ if (actual_state == SINK_STATE_CONNECTED) {
+ auto connection = delegate_->connection();
+ DCHECK(connection);
+ auto on_message = base::Bind(&WiFiDisplaySessionServiceImpl::OnSinkMessage,
+ weak_factory_.GetWeakPtr());
+ connection->SetMessageReceivedCallback(on_message);
+ client_->OnConnected(connection->GetLocalAddress());
+ }
+
+ if (actual_state == SINK_STATE_DISCONNECTED) {
+ client_->OnDisconnectRequestHandled(true, "");
+ client_->OnTerminated();
+ sink_id_ = DisplaySourceConnectionDelegate::kInvalidSinkId;
+ }
+
+ sink_state_ = actual_state;
+}
+
+void WiFiDisplaySessionServiceImpl::OnConnectionError(
+ int sink_id,
+ DisplaySourceErrorType type,
+ const std::string& description) {
+ if (sink_id != sink_id_)
+ return;
+ DCHECK(client_);
+ client_->OnError(type, description);
+}
+
+void WiFiDisplaySessionServiceImpl::OnConnectFailed(
+ int sink_id,
+ const std::string& message) {
+ if (sink_id != sink_id_)
+ return;
+ DCHECK(client_);
+ client_->OnError(ERROR_TYPE_CONNECTION_ERROR, message);
+}
+
+void WiFiDisplaySessionServiceImpl::OnDisconnectFailed(
+ int sink_id,
+ const std::string& message) {
+ if (sink_id != sink_id_)
+ return;
+ DCHECK(client_);
+ client_->OnDisconnectRequestHandled(false, message);
+}
+
+void WiFiDisplaySessionServiceImpl::OnClientConnectionError() {
+ DLOG(ERROR) << "IPC connection error";
+ delete this;
+}
+
+} // namespace extensions