summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormikhail.pozdnyakov <mikhail.pozdnyakov@intel.com>2016-02-11 11:42:24 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-11 19:43:47 +0000
commitef0d3aa8a2e82e6db356e112c236ef0f8a2a8918 (patch)
treec1d439680acee131a2290b1ca36b00dac9d3ebaa
parent0f0f3981f6ca07546cd9208c202ee512d4c807ba (diff)
downloadchromium_src-ef0d3aa8a2e82e6db356e112c236ef0f8a2a8918.zip
chromium_src-ef0d3aa8a2e82e6db356e112c236ef0f8a2a8918.tar.gz
chromium_src-ef0d3aa8a2e82e6db356e112c236ef0f8a2a8918.tar.bz2
[chrome.displaySource] Session notification improvements
This patch provides several fixes and improvements (simplifications) to the session life cycle notification mechanism: 1) The 'startSession'/'terminateSession' call completion callbacks are invoked when the session is actually started/terminated and in accordance with 'onSessionStarted'/'onSessionTerminated' events propagating (and as per documentation). 2) The notification from the required sink is filtered out in browser process avoiding unneeded IPC calls 3) Methods in mojo interface are renamed in order to improve readability BUG=242107 Review URL: https://codereview.chromium.org/1674583002 Cr-Commit-Position: refs/heads/master@{#374929}
-rw-r--r--extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.cc104
-rw-r--r--extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.h6
-rw-r--r--extensions/common/api/display_source.idl3
-rw-r--r--extensions/common/mojo/wifi_display_session_service.mojom8
-rw-r--r--extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc38
-rw-r--r--extensions/renderer/api/display_source/wifi_display/wifi_display_session.h9
-rw-r--r--extensions/renderer/display_source_custom_bindings.cc61
-rw-r--r--extensions/renderer/display_source_custom_bindings.h18
-rw-r--r--extensions/renderer/resources/display_source_custom_bindings.js66
9 files changed, 197 insertions, 116 deletions
diff --git a/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.cc b/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.cc
index 59dfda1..015eca3 100644
--- a/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.cc
+++ b/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.cc
@@ -23,20 +23,15 @@ WiFiDisplaySessionServiceImpl::WiFiDisplaySessionServiceImpl(
mojo::InterfaceRequest<WiFiDisplaySessionService> request)
: binding_(this, std::move(request)),
delegate_(delegate),
- last_connected_sink_(DisplaySourceConnectionDelegate::kInvalidSinkId),
- own_sink_(DisplaySourceConnectionDelegate::kInvalidSinkId),
+ sink_state_(SINK_STATE_NONE),
+ sink_id_(DisplaySourceConnectionDelegate::kInvalidSinkId),
weak_factory_(this) {
delegate_->AddObserver(this);
-
- auto connection = delegate_->connection();
- if (connection)
- last_connected_sink_ = connection->GetConnectedSink()->id;
}
WiFiDisplaySessionServiceImpl::~WiFiDisplaySessionServiceImpl() {
delegate_->RemoveObserver(this);
- if (own_sink_ != DisplaySourceConnectionDelegate::kInvalidSinkId)
- Disconnect();
+ Disconnect();
}
// static
@@ -67,7 +62,7 @@ void WiFiDisplaySessionServiceImpl::Connect(int32_t sink_id,
DCHECK(client_);
// We support only one Wi-Fi Display session at a time.
if (delegate_->connection()) {
- client_->OnError(sink_id, ERROR_TYPE_EXCEEDED_SESSION_LIMIT_ERROR,
+ client_->OnError(ERROR_TYPE_EXCEEDED_SESSION_LIMIT_ERROR,
kErrorCannotHaveMultipleSessions);
return;
}
@@ -77,7 +72,7 @@ void WiFiDisplaySessionServiceImpl::Connect(int32_t sink_id,
sinks.begin(), sinks.end(),
[sink_id](DisplaySourceSinkInfoPtr ptr) { return ptr->id == sink_id; });
if (found == sinks.end() || (*found)->state != SINK_STATE_DISCONNECTED) {
- client_->OnError(sink_id, ERROR_TYPE_ESTABLISH_CONNECTION_ERROR,
+ client_->OnError(ERROR_TYPE_ESTABLISH_CONNECTION_ERROR,
kErrorSinkNotAvailable);
return;
}
@@ -90,86 +85,113 @@ void WiFiDisplaySessionServiceImpl::Connect(int32_t sink_id,
auto on_error = base::Bind(&WiFiDisplaySessionServiceImpl::OnConnectFailed,
weak_factory_.GetWeakPtr(), sink_id);
delegate_->Connect(sink_id, auth_info, on_error);
- own_sink_ = sink_id;
+ sink_id_ = sink_id;
+ sink_state_ = (*found)->state;
+ DCHECK(sink_state_ == SINK_STATE_CONNECTING);
}
void WiFiDisplaySessionServiceImpl::Disconnect() {
- if (own_sink_ == DisplaySourceConnectionDelegate::kInvalidSinkId) {
+ if (sink_id_ == DisplaySourceConnectionDelegate::kInvalidSinkId) {
// The connection might drop before this call has arrived.
// Renderer should have been notified already.
return;
}
- DCHECK(delegate_->connection());
- DCHECK_EQ(own_sink_, delegate_->connection()->GetConnectedSink()->id);
+
+ const DisplaySourceSinkInfoList& sinks = delegate_->last_found_sinks();
+ auto found = std::find_if(
+ sinks.begin(), sinks.end(),
+ [this](DisplaySourceSinkInfoPtr ptr) { return ptr->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(), own_sink_);
+ weak_factory_.GetWeakPtr(), sink_id_);
delegate_->Disconnect(on_error);
}
void WiFiDisplaySessionServiceImpl::SendMessage(const mojo::String& message) {
- if (own_sink_ == DisplaySourceConnectionDelegate::kInvalidSinkId) {
+ if (sink_id_ == DisplaySourceConnectionDelegate::kInvalidSinkId) {
// The connection might drop before this call has arrived.
return;
}
auto connection = delegate_->connection();
DCHECK(connection);
- DCHECK_EQ(own_sink_, connection->GetConnectedSink()->id);
+ DCHECK_EQ(sink_id_, connection->GetConnectedSink()->id);
connection->SendMessage(message);
}
void WiFiDisplaySessionServiceImpl::OnSinkMessage(const std::string& message) {
DCHECK(delegate_->connection());
- DCHECK_NE(own_sink_, DisplaySourceConnectionDelegate::kInvalidSinkId);
+ DCHECK_NE(sink_id_, DisplaySourceConnectionDelegate::kInvalidSinkId);
DCHECK(client_);
client_->OnMessage(message);
}
void WiFiDisplaySessionServiceImpl::OnSinksUpdated(
const DisplaySourceSinkInfoList& sinks) {
- auto connection = delegate_->connection();
- if (!connection &&
- last_connected_sink_ != DisplaySourceConnectionDelegate::kInvalidSinkId) {
- if (last_connected_sink_ == own_sink_)
- own_sink_ = DisplaySourceConnectionDelegate::kInvalidSinkId;
- if (client_)
- client_->OnDisconnected(last_connected_sink_);
- last_connected_sink_ = DisplaySourceConnectionDelegate::kInvalidSinkId;
+ 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](DisplaySourceSinkInfoPtr ptr) { return ptr->id == sink_id_; });
+ if (found == sinks.end()) {
+ client_->OnError(ERROR_TYPE_CONNECTION_ERROR, "The sink has disappeared");
+ client_->OnTerminated();
+ sink_id_ = DisplaySourceConnectionDelegate::kInvalidSinkId;
}
- if (connection &&
- last_connected_sink_ != connection->GetConnectedSink()->id) {
- last_connected_sink_ = connection->GetConnectedSink()->id;
- if (client_)
- client_->OnConnected(last_connected_sink_, connection->GetLocalAddress());
- if (last_connected_sink_ == own_sink_) {
- auto on_message =
- base::Bind(&WiFiDisplaySessionServiceImpl::OnSinkMessage,
- weak_factory_.GetWeakPtr());
- connection->SetMessageReceivedCallback(on_message);
- }
+
+ 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_->OnEstablished(connection->GetLocalAddress());
}
+
+ if (actual_state == SINK_STATE_DISCONNECTED) {
+ 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(sink_id, type, description);
+ client_->OnError(type, description);
}
void WiFiDisplaySessionServiceImpl::OnConnectFailed(
int sink_id,
const std::string& message) {
+ if (sink_id != sink_id_)
+ return;
DCHECK(client_);
- client_->OnError(sink_id, ERROR_TYPE_ESTABLISH_CONNECTION_ERROR, message);
- own_sink_ = DisplaySourceConnectionDelegate::kInvalidSinkId;
+ client_->OnError(ERROR_TYPE_ESTABLISH_CONNECTION_ERROR, message);
}
void WiFiDisplaySessionServiceImpl::OnDisconnectFailed(
int sink_id,
const std::string& message) {
+ if (sink_id != sink_id_)
+ return;
DCHECK(client_);
- client_->OnError(sink_id, ERROR_TYPE_CONNECTION_ERROR, message);
+ client_->OnError(ERROR_TYPE_CONNECTION_ERROR, message);
}
void WiFiDisplaySessionServiceImpl::OnClientConnectionError() {
diff --git a/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.h b/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.h
index e50237c..6639871 100644
--- a/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.h
+++ b/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.h
@@ -61,11 +61,9 @@ class WiFiDisplaySessionServiceImpl
WiFiDisplaySessionServiceClientPtr client_;
DisplaySourceConnectionDelegate* delegate_;
- // Id of the currenty connected sink (if any), obtained from connection
- // delegate. Keep it so that we know if a session has been ended.
- int last_connected_sink_;
+ api::display_source::SinkState sink_state_;
// Id of the sink of the session this object is associated with.
- int own_sink_;
+ int sink_id_;
base::WeakPtrFactory<WiFiDisplaySessionServiceImpl> weak_factory_;
diff --git a/extensions/common/api/display_source.idl b/extensions/common/api/display_source.idl
index f65a82a..83cfa0d 100644
--- a/extensions/common/api/display_source.idl
+++ b/extensions/common/api/display_source.idl
@@ -144,9 +144,6 @@ namespace displaySource {
// or properties)
// |sinks| the list of all currently available sinks
static void onSinksUpdated(SinkInfo[] sinks);
- // Event fired when the Display session is started.
- // |sinkId| Id of the peer sink
- [nocompile] static void onSessionStarted(long sinkId);
// Event fired when the Display session is terminated.
// |sinkId| Id of the peer sink
[nocompile] static void onSessionTerminated(long sinkId);
diff --git a/extensions/common/mojo/wifi_display_session_service.mojom b/extensions/common/mojo/wifi_display_session_service.mojom
index e302256..637a1f0 100644
--- a/extensions/common/mojo/wifi_display_session_service.mojom
+++ b/extensions/common/mojo/wifi_display_session_service.mojom
@@ -21,13 +21,13 @@ interface WiFiDisplaySessionService {
interface WiFiDisplaySessionServiceClient {
// Notification of a successfull connection to a sink.
- OnConnected(int32 sink_id, string ip_address);
+ OnEstablished(string ip_address);
- // Notification of a connection termination.
- OnDisconnected(int32 sink_id);
+ // Notification of a session termination.
+ OnTerminated();
// Notification of an error occurred during the session.
- OnError(int32 sink_id, int32 type, string description);
+ OnError(int32 type, string description);
// Invoked to transmit a controlling message from
// the connected sink.
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc b/extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc
index 67edf4b..f6d1104 100644
--- a/extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc
+++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc
@@ -42,6 +42,8 @@ void WiFiDisplaySession::Start() {
DCHECK(state_ == DisplaySourceSession::Idle);
service_->Connect(params_.sink_id, params_.auth_method, params_.auth_data);
state_ = DisplaySourceSession::Establishing;
+ if (!started_callback_.is_null())
+ started_callback_.Run(params_.sink_id);
}
void WiFiDisplaySession::Terminate() {
@@ -61,35 +63,26 @@ void WiFiDisplaySession::Terminate() {
}
}
-void WiFiDisplaySession::OnConnected(
- int32_t sink_id, const mojo::String& ip_address) {
- if (sink_id == params_.sink_id) {
- DCHECK(state_ != DisplaySourceSession::Established);
- ip_address_ = ip_address;
- state_ = DisplaySourceSession::Established;
- }
-
- if (!started_callback_.is_null())
- started_callback_.Run(sink_id);
+void WiFiDisplaySession::OnEstablished(const mojo::String& ip_address) {
+ DCHECK(state_ != DisplaySourceSession::Established);
+ ip_address_ = ip_address;
+ state_ = DisplaySourceSession::Established;
}
-void WiFiDisplaySession::OnDisconnected(int32_t sink_id) {
- if (sink_id == params_.sink_id) {
- DCHECK(state_ == DisplaySourceSession::Established ||
- state_ == DisplaySourceSession::Terminating);
- state_ = DisplaySourceSession::Idle;
- }
-
+void WiFiDisplaySession::OnTerminated() {
+ DCHECK(state_ != DisplaySourceSession::Idle);
+ state_ = DisplaySourceSession::Idle;
if (!terminated_callback_.is_null())
- terminated_callback_.Run(sink_id);
+ terminated_callback_.Run(params_.sink_id);
}
-void WiFiDisplaySession::OnError(
- int32_t sink_id, int32_t type, const mojo::String& description) {
+void WiFiDisplaySession::OnError(int32_t type,
+ const mojo::String& description) {
DCHECK(type > api::display_source::ERROR_TYPE_NONE
&& type <= api::display_source::ERROR_TYPE_LAST);
if (!error_callback_.is_null())
- error_callback_.Run(sink_id, static_cast<ErrorType>(type), description);
+ error_callback_.Run(params_.sink_id, static_cast<ErrorType>(type),
+ description);
}
void WiFiDisplaySession::OnMessage(const mojo::String& data) {
@@ -103,8 +96,7 @@ void WiFiDisplaySession::OnConnectionError() {
kErrorInternal);
}
- if (state_ == DisplaySourceSession::Established ||
- state_ == DisplaySourceSession::Terminating) {
+ if (state_ != DisplaySourceSession::Idle) {
// We must explicitly notify the session termination as it will never
// arrive from browser process (IPC is broken).
if (!terminated_callback_.is_null())
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_session.h b/extensions/renderer/api/display_source/wifi_display/wifi_display_session.h
index b807993..5d10308 100644
--- a/extensions/renderer/api/display_source/wifi_display/wifi_display_session.h
+++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_session.h
@@ -26,12 +26,9 @@ class WiFiDisplaySession: public DisplaySourceSession,
void Terminate() override;
// WiFiDisplaySessionServiceClient overrides.
- void OnConnected(int32_t sink_id,
- const mojo::String& ip_address) override;
- void OnDisconnected(int32_t sink_id) override;
- void OnError(int32_t sink_id,
- int32_t type,
- const mojo::String& description) override;
+ void OnEstablished(const mojo::String& ip_address) override;
+ void OnTerminated() override;
+ void OnError(int32_t type, const mojo::String& description) override;
void OnMessage(const mojo::String& data) override;
// A connection error handler for the mojo objects used in this class.
diff --git a/extensions/renderer/display_source_custom_bindings.cc b/extensions/renderer/display_source_custom_bindings.cc
index 50752c0..ab68553 100644
--- a/extensions/renderer/display_source_custom_bindings.cc
+++ b/extensions/renderer/display_source_custom_bindings.cc
@@ -71,8 +71,10 @@ v8::Local<v8::Value> GetChildValue(v8::Local<v8::Object> value,
void DisplaySourceCustomBindings::StartSession(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- CHECK_EQ(1, args.Length());
+ CHECK_EQ(2, args.Length());
CHECK(args[0]->IsObject());
+ CHECK(args[1]->IsFunction());
+
v8::Isolate* isolate = context()->isolate();
v8::Local<v8::Object> start_info = args[0].As<v8::Object>();
@@ -164,14 +166,20 @@ void DisplaySourceCustomBindings::StartSession(
session->SetCallbacks(on_started_callback,
on_terminated_callback,
on_error_callback);
+
+ CallbackInfo cb_info = GetCallbackInfo(kStarted, sink_id);
+ args.GetReturnValue().Set(static_cast<int32_t>(cb_info.call_id));
+ callbacks_.push_back(cb_info);
+
session->Start();
session_map_.insert(std::make_pair(sink_id, std::move(session)));
}
void DisplaySourceCustomBindings::TerminateSession(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- CHECK_EQ(1, args.Length());
+ CHECK_EQ(2, args.Length());
CHECK(args[0]->IsInt32());
+ CHECK(args[1]->IsFunction());
v8::Isolate* isolate = context()->isolate();
int sink_id = args[0]->ToInt32(args.GetIsolate())->Value();
@@ -187,17 +195,40 @@ void DisplaySourceCustomBindings::TerminateSession(
isolate, kSessionAlreadyTerminating)));
return;
}
+
+ CallbackInfo cb_info = GetCallbackInfo(kTerminated, sink_id);
+ args.GetReturnValue().Set(static_cast<int32_t>(cb_info.call_id));
+ callbacks_.push_back(cb_info);
+
// The session will get removed from session_map_ in OnSessionTerminated.
session->Terminate();
}
-void DisplaySourceCustomBindings::DispatchSessionStarted(int sink_id) const {
+void DisplaySourceCustomBindings::CallCompletionCallback(
+ int sink_id,
+ CallbackType type,
+ const std::string& error_message) {
+ auto predicate = [sink_id, type](const CallbackInfo& info) -> bool {
+ return info.sink_id == sink_id && info.type == type;
+ };
+ auto it = std::find_if(callbacks_.begin(), callbacks_.end(), predicate);
+ if (it == callbacks_.end())
+ return;
+
v8::Isolate* isolate = context()->isolate();
+ ModuleSystem* module_system = context()->module_system();
v8::HandleScope handle_scope(isolate);
v8::Context::Scope context_scope(context()->v8_context());
- v8::Local<v8::Array> event_args = v8::Array::New(isolate, 1);
- event_args->Set(0, v8::Integer::New(isolate, sink_id));
- context()->DispatchEvent("displaySource.onSessionStarted", event_args);
+
+ v8::Local<v8::Value> callback_args[2];
+ callback_args[0] = v8::Integer::New(isolate, it->call_id);
+ if (error_message.empty())
+ callback_args[1] = v8::Null(isolate);
+ else
+ callback_args[1] = v8::String::NewFromUtf8(isolate, error_message.c_str());
+
+ module_system->CallModuleMethod("displaySource", "callCompletionCallback", 2,
+ callback_args);
}
void DisplaySourceCustomBindings::DispatchSessionTerminated(int sink_id) const {
@@ -242,7 +273,7 @@ DisplaySourceSession* DisplaySourceCustomBindings::GetDisplaySession(
}
void DisplaySourceCustomBindings::OnSessionStarted(int sink_id) {
- DispatchSessionStarted(sink_id);
+ CallCompletionCallback(sink_id, kStarted);
}
void DisplaySourceCustomBindings::OnSessionTerminated(int sink_id) {
@@ -250,6 +281,7 @@ void DisplaySourceCustomBindings::OnSessionTerminated(int sink_id) {
CHECK(session);
session_map_.erase(sink_id);
DispatchSessionTerminated(sink_id);
+ CallCompletionCallback(sink_id, kTerminated);
}
void DisplaySourceCustomBindings::OnSessionError(int sink_id,
@@ -257,14 +289,15 @@ void DisplaySourceCustomBindings::OnSessionError(int sink_id,
const std::string& message) {
DisplaySourceSession* session = GetDisplaySession(sink_id);
CHECK(session);
- if (session->state() != DisplaySourceSession::Established &&
- session->state() != DisplaySourceSession::Terminating) {
- // Error has occured before the session has actually started,
- // no need to wait for session termination notification.
- session_map_.erase(sink_id);
- }
-
DispatchSessionError(sink_id, type, message);
}
+DisplaySourceCustomBindings::CallbackInfo
+DisplaySourceCustomBindings::GetCallbackInfo(
+ DisplaySourceCustomBindings::CallbackType type,
+ int sink_id) const {
+ static int sCallId = 0;
+ return {type, sink_id, ++sCallId};
+}
+
} // extensions
diff --git a/extensions/renderer/display_source_custom_bindings.h b/extensions/renderer/display_source_custom_bindings.h
index 199f199..2a65445 100644
--- a/extensions/renderer/display_source_custom_bindings.h
+++ b/extensions/renderer/display_source_custom_bindings.h
@@ -29,8 +29,12 @@ class DisplaySourceCustomBindings : public ObjectBackedNativeHandler {
const v8::FunctionCallbackInfo<v8::Value>& args);
void TerminateSession(
const v8::FunctionCallbackInfo<v8::Value>& args);
-
- void DispatchSessionStarted(int sink_id) const;
+ // Call completion callbacks.
+ enum CallbackType { kStarted, kTerminated };
+ void CallCompletionCallback(int sink_id,
+ CallbackType type,
+ const std::string& error_message = "");
+ // Dispatch events
void DispatchSessionTerminated(int sink_id) const;
void DispatchSessionError(int sink_id,
DisplaySourceErrorType type,
@@ -46,6 +50,16 @@ class DisplaySourceCustomBindings : public ObjectBackedNativeHandler {
DisplaySourceSession* GetDisplaySession(int sink_id) const;
std::map<int, scoped_ptr<DisplaySourceSession>> session_map_;
+ // Data of a call completion callback.
+ struct CallbackInfo {
+ CallbackType type;
+ int sink_id;
+ int call_id; // Each call has a unique Id.
+ };
+
+ CallbackInfo GetCallbackInfo(CallbackType type, int sink_id) const;
+
+ std::vector<CallbackInfo> callbacks_;
base::WeakPtrFactory<DisplaySourceCustomBindings> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(DisplaySourceCustomBindings);
diff --git a/extensions/renderer/resources/display_source_custom_bindings.js b/extensions/renderer/resources/display_source_custom_bindings.js
index 13e8167..a1345ff 100644
--- a/extensions/renderer/resources/display_source_custom_bindings.js
+++ b/extensions/renderer/resources/display_source_custom_bindings.js
@@ -8,34 +8,62 @@ var binding = require('binding').Binding.create('displaySource');
var chrome = requireNative('chrome').GetChrome();
var lastError = require('lastError');
var natives = requireNative('display_source');
+var logging = requireNative('logging');
+
+var callbacksInfo = {};
+
+function callbackWrapper(callback, method, message) {
+ if (callback == undefined)
+ return;
+
+ try {
+ if (message !== null)
+ lastError.set('displaySource.startSession', message, null, chrome);
+ callback();
+ } finally {
+ lastError.clear(chrome);
+ }
+}
+
+function callCompletionCallback(callbackId, error_message) {
+ try {
+ var callbackInfo = callbacksInfo[callbackId];
+ logging.DCHECK(callbackInfo != null);
+ callbackWrapper(callbackInfo.callback, callbackInfo.method, error_message);
+ } finally {
+ delete callbacksInfo[callbackId];
+ }
+}
binding.registerCustomHook(function(bindingsAPI, extensionId) {
var apiFunctions = bindingsAPI.apiFunctions;
- apiFunctions.setHandleRequest('startSession',
- function(sessionInfo, callback) {
+ apiFunctions.setHandleRequest(
+ 'startSession', function(sessionInfo, callback) {
try {
- natives.StartSession(sessionInfo);
+ var callId = natives.StartSession(sessionInfo, callbackWrapper);
+ callbacksInfo[callId] = {
+ callback: callback,
+ method: 'displaySource.startSession'
+ };
} catch (e) {
- lastError.set('displaySource.startSession', e.message, null, chrome);
- } finally {
- if (callback !== undefined)
- callback();
- lastError.clear(chrome);
+ callbackWrapper(callback, 'displaySource.startSession', e.message);
}
- });
- apiFunctions.setHandleRequest('terminateSession',
- function(sink_id, callback) {
+ });
+ apiFunctions.setHandleRequest(
+ 'terminateSession', function(sink_id, callback) {
try {
- natives.TerminateSession(sink_id);
+ var callId = natives.TerminateSession(sink_id, callbackWrapper);
+ callbacksInfo[callId] = {
+ callback: callback,
+ method: 'displaySource.terminateSession'
+ };
} catch (e) {
- lastError.set(
- 'displaySource.terminateSession', e.message, null, chrome);
- } finally {
- if (callback !== undefined)
- callback();
- lastError.clear(chrome);
+ callbackWrapper(
+ callback, 'displaySource.terminateSession', e.message);
}
- });
+ });
});
exports.$set('binding', binding.generate());
+// Called by C++.
+exports.$set('callCompletionCallback', callCompletionCallback);