diff options
author | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-06 00:01:24 +0000 |
---|---|---|
committer | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-06 00:01:24 +0000 |
commit | 1b21a1d7b67e14e121d1b050b83942145e960853 (patch) | |
tree | 8f99fed3fd6a8d330e7fd80bcfb80dda6f849def | |
parent | ca8dfe8b30b745c17b9a25ebe09d1de23d50e9b4 (diff) | |
download | chromium_src-1b21a1d7b67e14e121d1b050b83942145e960853.zip chromium_src-1b21a1d7b67e14e121d1b050b83942145e960853.tar.gz chromium_src-1b21a1d7b67e14e121d1b050b83942145e960853.tar.bz2 |
[Sync] Refactor JS event handling to reduce boilerplate
Split event handlers/routers to handle events and message replies
separately.
Reduce JS boilerplate.
Use OVERRIDE where appropriate.
BUG=
TEST=
Review URL: http://codereview.chromium.org/6930030
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@84357 0039d316-1c4b-4281-b951-d872f2087c98
21 files changed, 306 insertions, 328 deletions
diff --git a/chrome/browser/resources/sync_internals/chrome_sync.js b/chrome/browser/resources/sync_internals/chrome_sync.js index 4b452742..8d2dcbf 100644 --- a/chrome/browser/resources/sync_internals/chrome_sync.js +++ b/chrome/browser/resources/sync_internals/chrome_sync.js @@ -46,7 +46,7 @@ Event.prototype.findListener_ = function(listener) { // Fires the event. Called by the actual event callback. Any // exceptions thrown by a listener are caught and logged. -Event.prototype.dispatch_ = function() { +Event.prototype.fire = function() { var args = Array.prototype.slice.call(arguments); for (var i = 0; i < this.listeners_.length; i++) { try { @@ -62,182 +62,78 @@ Event.prototype.dispatch_ = function() { } }; -// Service events. -chrome.sync.onSyncServiceStateChanged = new Event(); - -// Notifier events. -chrome.sync.onSyncNotificationStateChange = new Event(); -chrome.sync.onSyncIncomingNotification = new Event(); - -// Manager events. -chrome.sync.onChangesApplied = new Event(); -chrome.sync.onChangesComplete = new Event(); -chrome.sync.onSyncCycleCompleted = new Event(); -chrome.sync.onAuthError = new Event(); -chrome.sync.onUpdatedToken = new Event(); -chrome.sync.onPassphraseRequired = new Event(); -chrome.sync.onPassphraseAccepted = new Event(); -chrome.sync.onEncryptionComplete = new Event(); -chrome.sync.onMigrationNeededForTypes = new Event(); -chrome.sync.onInitializationComplete = new Event(); -chrome.sync.onPaused = new Event(); -chrome.sync.onResumed = new Event(); -chrome.sync.onStopSyncingPermanently = new Event(); -chrome.sync.onClearServerDataSucceeded = new Event(); -chrome.sync.onClearServerDataFailed = new Event(); - -function AsyncFunction(name) { - this.name_ = name; - this.callbacks_ = []; -} - -// Calls the function, assuming the last argument is a callback to be -// called with the return value. -AsyncFunction.prototype.call = function() { - var args = Array.prototype.slice.call(arguments); - this.callbacks_.push(args.pop()); - chrome.send(this.name_, args); -} - -// Handle a reply, assuming that messages are processed in FIFO order. -AsyncFunction.prototype.handleReply = function() { - var args = Array.prototype.slice.call(arguments); - // Remove the callback before we call it since the callback may - // throw. - var callback = this.callbacks_.shift(); - callback.apply(null, args); -} - -// Sync service functions. -chrome.sync.getAboutInfo_ = new AsyncFunction('getAboutInfo'); -chrome.sync.getAboutInfo = function(callback) { - chrome.sync.getAboutInfo_.call(callback); -} - -// Notification functions. -chrome.sync.getNotificationState_ = - new AsyncFunction('getNotificationState'); -chrome.sync.getNotificationState = function(callback) { - chrome.sync.getNotificationState_.call(callback); -} - -chrome.sync.getNotificationInfo_ = - new AsyncFunction('getNotificationInfo'); -chrome.sync.getNotificationInfo = function(callback) { - chrome.sync.getNotificationInfo_.call(callback); -} - -// Node lookup functions. -chrome.sync.getRootNode_ = new AsyncFunction('getRootNode'); -chrome.sync.getRootNode = function(callback) { - chrome.sync.getRootNode_.call(callback); -} - -chrome.sync.getNodeById_ = new AsyncFunction('getNodeById'); -chrome.sync.getNodeById = function(id, callback) { - chrome.sync.getNodeById_.call(id, callback); +var events = [ + // Service events. + 'onSyncServiceStateChanged', + + // Notifier events. + 'onSyncNotificationStateChange', + 'onSyncIncomingNotification', + + // Manager events. + 'onChangesApplied', + 'onChangesComplete', + 'onSyncCycleCompleted', + 'onAuthError', + 'onUpdatedToken', + 'onPassphraseRequired', + 'onPassphraseAccepted', + 'onEncryptionComplete', + 'onMigrationNeededForTypes', + 'onInitializationComplete', + 'onPaused', + 'onResumed', + 'onStopSyncingPermanently', + 'onClearServerDataSucceeded', + 'onClearServerDataFailed' +]; + +for (var i = 0; i < events.length; ++i) { + var event = events[i]; + chrome.sync[event] = new Event(); +} + +function makeAsyncFunction(name) { + var callbacks = []; + + // Calls the function, assuming the last argument is a callback to be + // called with the return value. + var fn = function() { + var args = Array.prototype.slice.call(arguments); + callbacks.push(args.pop()); + chrome.send(name, args); + }; + + // Handle a reply, assuming that messages are processed in FIFO order. + // Called by SyncInternalsUI::HandleJsMessageReply(). + fn.handleReply = function() { + var args = Array.prototype.slice.call(arguments); + // Remove the callback before we call it since the callback may + // throw. + var callback = callbacks.shift(); + callback.apply(null, args); + }; + + return fn; +} + +var syncFunctions = [ + // Sync service functions. + 'getAboutInfo', + + // Notification functions. + 'getNotificationState', + 'getNotificationInfo', + + // Node lookup functions. + 'getRootNode', + 'getNodeById', + 'findNodesContainingString' +]; + +for (var i = 0; i < syncFunctions.length; ++i) { + var syncFunction = syncFunctions[i]; + chrome.sync[syncFunction] = makeAsyncFunction(syncFunction); } })(); - -// TODO(akalin): Rewrite the C++ side to not need the handlers below. - -// Sync service event handlers. - -function onSyncServiceStateChanged() { - chrome.sync.onSyncServiceStateChanged.dispatch_(); -} - -// Notification event handlers. - -function onSyncNotificationStateChange(notificationsEnabled) { - chrome.sync.onSyncNotificationStateChange.dispatch_(notificationsEnabled); -} - -function onSyncIncomingNotification(changedTypes) { - chrome.sync.onSyncIncomingNotification.dispatch_(changedTypes); -} - -// Sync manager event handlers. - -function onChangesApplied(modelType, changes) { - chrome.sync.onChangesApplied.dispatch_(modelType, changes); -} - -function onChangesComplete(modelType) { - chrome.sync.onChangesComplete.dispatch_(modelType); -} - -function onSyncCycleCompleted(snapshot) { - chrome.sync.onSyncCycleCompleted.dispatch_(snapshot); -} - -function onAuthError(authError) { - chrome.sync.onAuthError.dispatch_(authError); -} - -function onUpdatedToken(token) { - chrome.sync.onUpdatedToken.dispatch_(token); -} - -function onPassphraseRequired(reason) { - chrome.sync.onPassphraseRequired.dispatch_(reason); -} - -function onPassphraseAccepted(bootstrapToken) { - chrome.sync.onPassphraseAccepted.dispatch_(bootstrapToken); -} - -function onEncryptionComplete(encrypted_types) { - chrome.sync.onEncryptionComplete.dispatch_(encrypted_types); -} - -function onMigrationNeededForTypes(model_types) { - chrome.sync.onMigrationNeededForTypes.dispatch_(model_types); -} - -function onInitializationComplete() { - chrome.sync.onInitializationComplete.dispatch_(); -} - -function onPaused() { - chrome.sync.onPaused.dispatch_(); -} - -function onResumed() { - chrome.sync.onResumed.dispatch_(); -} - -function onStopSyncingPermanently() { - chrome.sync.onStopSyncingPermanently.dispatch_(); -} - -function onClearServerDataSucceeded() { - chrome.sync.onClearServerDataSucceeded(); -} - -function onClearServerDataFailed() { - chrome.sync.onClearServerDataFailed(); -} - -// Function reply handlers. - -function onGetAboutInfoFinished(aboutInfo) { - chrome.sync.getAboutInfo_.handleReply(aboutInfo); -} - -function onGetNotificationStateFinished(notificationState) { - chrome.sync.getNotificationState_.handleReply(notificationState); -} - -function onGetRootNodeFinished(rootNode) { - chrome.sync.getRootNode_.handleReply(rootNode); -} - -function onGetNodeByIdFinished(node) { - chrome.sync.getNodeById_.handleReply(node); -} - -function onGetNotificationInfoFinished(notificationInfo) { - chrome.sync.getNotificationInfo_.handleReply(notificationInfo); -} diff --git a/chrome/browser/sync/README.js b/chrome/browser/sync/README.js index db12140..d8c86aa 100644 --- a/chrome/browser/sync/README.js +++ b/chrome/browser/sync/README.js @@ -5,9 +5,8 @@ This note explains how chrome://sync-internals (also known as about:sync) interacts with the sync service/backend. Basically, chrome://sync-internals sends asynchronous messages to the -sync backend and the sync backend asynchronously raises events to -chrome://sync-internals, either when replying to messages or when -something interesting happens. +sync backend and the sync backend asynchronously raises events and +message replies to chrome://sync-internals. Both messages and events have a name and a list of arguments, the latter of which is represented by a JsArgList (js_arg_list.h) object, @@ -19,7 +18,7 @@ Message/event flow ------------------ chrome://sync-internals is represented by SyncInternalsUI -(chrome/browser/web_ui/sync_internals_ui.h). SyncInternalsUI +(chrome/browser/ui/webui/sync_internals_ui.h). SyncInternalsUI interacts with the sync service via a JsFrontend (js_frontend.h) object, which has a ProcessMessage() method. The JsFrontend can handle some messages itself, but it can also delegate the rest to a @@ -36,14 +35,14 @@ JsBackends may live on different threads, but JsArgList is thread-safe so that's okay. SyncInternalsUI is a JsEventHandler (js_event_handler.h), which means -that it has a HandleJsEvent() method, but JsBackends cannot easily -access those objects. Instead, each JsBackend keeps track of its -parent router, which is a JsEventRouter object (js_event_router.h). -Basically, a JsEventRouter is another JsBackend object or a JsFrontend -object. So an event travels up through the JsEventRouter until it -reaches the JsFrontend, which knows about the existing JsEventHandlers -(via AddHandler()/RemoveHandler()) and so can delegate to the right -one. +that it has a HandleJsEvent() method and a HandleJsMessageReply() +method, but JsBackends cannot easily access those objects. Instead, +each JsBackend keeps track of its parent router, which is a +JsEventRouter object (js_event_router.h). Basically, a JsEventRouter +is another JsBackend object or a JsFrontend object. So an event or +message reply travels up through the JsEventRouter until it reaches +the JsFrontend, which knows about the existing JsEventHandlers (via +AddHandler()/RemoveHandler()) and so can delegate to the right one. A diagram of the flow of a message and its reply: diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc index 6cf7408..f7df069 100644 --- a/chrome/browser/sync/engine/syncapi.cc +++ b/chrome/browser/sync/engine/syncapi.cc @@ -1404,12 +1404,15 @@ class SyncManager::SyncInternal virtual void OnServerConnectionEvent(const ServerConnectionEvent& event); // browser_sync::JsBackend implementation. - virtual void SetParentJsEventRouter(browser_sync::JsEventRouter* router); - virtual void RemoveParentJsEventRouter(); - virtual const browser_sync::JsEventRouter* GetParentJsEventRouter() const; - virtual void ProcessMessage(const std::string& name, - const browser_sync::JsArgList& args, - const browser_sync::JsEventHandler* sender); + virtual void SetParentJsEventRouter( + browser_sync::JsEventRouter* router) OVERRIDE; + virtual void RemoveParentJsEventRouter() OVERRIDE; + virtual const browser_sync::JsEventRouter* + GetParentJsEventRouter() const OVERRIDE; + virtual void ProcessMessage( + const std::string& name, + const browser_sync::JsArgList& args, + const browser_sync::JsEventHandler* sender) OVERRIDE; ListValue* FindNodesContainingString(const std::string& query); @@ -2627,9 +2630,8 @@ void SyncManager::SyncInternal::ProcessMessage( bool notifications_enabled = allstatus_.status().notifications_enabled; ListValue return_args; return_args.Append(Value::CreateBooleanValue(notifications_enabled)); - parent_router_->RouteJsEvent( - "onGetNotificationStateFinished", - browser_sync::JsArgList(return_args), sender); + parent_router_->RouteJsMessageReply( + name, browser_sync::JsArgList(return_args), sender); } else if (name == "getNotificationInfo") { if (!parent_router_) { LogNoRouter(name, args); @@ -2638,8 +2640,8 @@ void SyncManager::SyncInternal::ProcessMessage( ListValue return_args; return_args.Append(NotificationInfoToValue(notification_info_map_)); - parent_router_->RouteJsEvent("onGetNotificationInfoFinished", - browser_sync::JsArgList(return_args), sender); + parent_router_->RouteJsMessageReply( + name, browser_sync::JsArgList(return_args), sender); } else if (name == "getRootNode") { if (!parent_router_) { LogNoRouter(name, args); @@ -2650,24 +2652,22 @@ void SyncManager::SyncInternal::ProcessMessage( root.InitByRootLookup(); ListValue return_args; return_args.Append(root.ToValue()); - parent_router_->RouteJsEvent( - "onGetRootNodeFinished", - browser_sync::JsArgList(return_args), sender); + parent_router_->RouteJsMessageReply( + name, browser_sync::JsArgList(return_args), sender); } else if (name == "getNodeById") { if (!parent_router_) { LogNoRouter(name, args); return; } - parent_router_->RouteJsEvent( - "onGetNodeByIdFinished", ProcessGetNodeByIdMessage(args), sender); + parent_router_->RouteJsMessageReply( + name, ProcessGetNodeByIdMessage(args), sender); } else if (name == "findNodesContainingString") { if (!parent_router_) { LogNoRouter(name, args); return; } - parent_router_->RouteJsEvent( - "onFindNodesContainingStringFinished", - ProcessFindNodesContainingString(args), sender); + parent_router_->RouteJsMessageReply( + name, ProcessFindNodesContainingString(args), sender); } else { VLOG(1) << "Dropping unknown message " << name << " with args " << args.ToString(); @@ -2728,7 +2728,7 @@ void SyncManager::SyncInternal::OnNotificationStateChange( args.Append(Value::CreateBooleanValue(notifications_enabled)); // TODO(akalin): Tidy up grammar in event names. parent_router_->RouteJsEvent("onSyncNotificationStateChange", - browser_sync::JsArgList(args), NULL); + browser_sync::JsArgList(args)); } } @@ -2769,7 +2769,7 @@ void SyncManager::SyncInternal::OnIncomingNotification( changed_types->Append(Value::CreateStringValue(model_type_str)); } parent_router_->RouteJsEvent("onSyncIncomingNotification", - browser_sync::JsArgList(args), NULL); + browser_sync::JsArgList(args)); } } diff --git a/chrome/browser/sync/engine/syncapi_unittest.cc b/chrome/browser/sync/engine/syncapi_unittest.cc index 465a642..6ccf8f0 100644 --- a/chrome/browser/sync/engine/syncapi_unittest.cc +++ b/chrome/browser/sync/engine/syncapi_unittest.cc @@ -807,18 +807,19 @@ TEST_F(SyncManagerTest, ProcessMessage) { false_args.Append(Value::CreateBooleanValue(false)); EXPECT_CALL(event_router, - RouteJsEvent("onGetNotificationStateFinished", - HasArgsAsList(false_args), &event_handler)); + RouteJsMessageReply("getNotificationState", + HasArgsAsList(false_args), + &event_handler)); js_backend->SetParentJsEventRouter(&event_router); // This message should be dropped. js_backend->ProcessMessage("unknownMessage", - kNoArgs, &event_handler); + kNoArgs, &event_handler); // This should trigger the reply. js_backend->ProcessMessage("getNotificationState", - kNoArgs, &event_handler); + kNoArgs, &event_handler); js_backend->RemoveParentJsEventRouter(); } @@ -828,9 +829,9 @@ TEST_F(SyncManagerTest, ProcessMessage) { { StrictMock<MockJsEventHandler> event_handler; js_backend->ProcessMessage("unknownMessage", - kNoArgs, &event_handler); + kNoArgs, &event_handler); js_backend->ProcessMessage("getNotificationState", - kNoArgs, &event_handler); + kNoArgs, &event_handler); } } @@ -845,8 +846,8 @@ TEST_F(SyncManagerTest, ProcessMessageGetRootNode) { JsArgList return_args; EXPECT_CALL(event_router, - RouteJsEvent("onGetRootNodeFinished", _, &event_handler)). - WillOnce(SaveArg<1>(&return_args)); + RouteJsMessageReply("getRootNode", _, &event_handler)) + .WillOnce(SaveArg<1>(&return_args)); js_backend->SetParentJsEventRouter(&event_router); @@ -896,7 +897,7 @@ TEST_F(SyncManagerTest, ProcessMessageGetNodeById) { JsArgList return_args; EXPECT_CALL(event_router, - RouteJsEvent("onGetNodeByIdFinished", _, &event_handler)) + RouteJsMessageReply("getNodeById", _, &event_handler)) .Times(2).WillRepeatedly(SaveArg<1>(&return_args)); js_backend->SetParentJsEventRouter(&event_router); @@ -932,8 +933,8 @@ TEST_F(SyncManagerTest, ProcessMessageGetNodeByIdFailure) { null_args.Append(Value::CreateNullValue()); EXPECT_CALL(event_router, - RouteJsEvent("onGetNodeByIdFinished", - HasArgsAsList(null_args), &event_handler)) + RouteJsMessageReply("getNodeById", HasArgsAsList(null_args), + &event_handler)) .Times(5); js_backend->SetParentJsEventRouter(&event_router); @@ -982,10 +983,10 @@ TEST_F(SyncManagerTest, OnNotificationStateChange) { EXPECT_CALL(event_router, RouteJsEvent("onSyncNotificationStateChange", - HasArgsAsList(true_args), NULL)); + HasArgsAsList(true_args))); EXPECT_CALL(event_router, RouteJsEvent("onSyncNotificationStateChange", - HasArgsAsList(false_args), NULL)); + HasArgsAsList(false_args))); browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend(); @@ -1028,7 +1029,7 @@ TEST_F(SyncManagerTest, OnIncomingNotification) { EXPECT_CALL(event_router, RouteJsEvent("onSyncIncomingNotification", - HasArgsAsList(expected_args), NULL)); + HasArgsAsList(expected_args))); browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend(); diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc index 782d922..d039471 100644 --- a/chrome/browser/sync/glue/sync_backend_host.cc +++ b/chrome/browser/sync/glue/sync_backend_host.cc @@ -1024,11 +1024,19 @@ void SyncBackendHost::Core::OnEncryptionComplete( } void SyncBackendHost::Core::RouteJsEvent( + const std::string& name, const JsArgList& args) { + host_->frontend_loop_->PostTask( + FROM_HERE, NewRunnableMethod( + this, &Core::RouteJsEventOnFrontendLoop, name, args)); +} + +void SyncBackendHost::Core::RouteJsMessageReply( const std::string& name, const JsArgList& args, const JsEventHandler* target) { host_->frontend_loop_->PostTask( FROM_HERE, NewRunnableMethod( - this, &Core::RouteJsEventOnFrontendLoop, name, args, target)); + this, &Core::RouteJsMessageReplyOnFrontendLoop, + name, args, target)); } void SyncBackendHost::Core::HandleStopSyncingPermanentlyOnFrontendLoop() { @@ -1061,6 +1069,16 @@ void SyncBackendHost::Core::HandleAuthErrorEventOnFrontendLoop( } void SyncBackendHost::Core::RouteJsEventOnFrontendLoop( + const std::string& name, const JsArgList& args) { + if (!host_ || !parent_router_) + return; + + DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_); + + parent_router_->RouteJsEvent(name, args); +} + +void SyncBackendHost::Core::RouteJsMessageReplyOnFrontendLoop( const std::string& name, const JsArgList& args, const JsEventHandler* target) { if (!host_ || !parent_router_) @@ -1068,7 +1086,7 @@ void SyncBackendHost::Core::RouteJsEventOnFrontendLoop( DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_); - parent_router_->RouteJsEvent(name, args, target); + parent_router_->RouteJsMessageReply(name, args, target); } void SyncBackendHost::Core::StartSavingChanges() { diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h index b36adea..6002dae 100644 --- a/chrome/browser/sync/glue/sync_backend_host.h +++ b/chrome/browser/sync/glue/sync_backend_host.h @@ -10,6 +10,7 @@ #include <string> #include <vector> +#include "base/compiler_specific.h" #include "base/file_path.h" #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" @@ -292,16 +293,18 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar { const syncable::ModelTypeSet& encrypted_types); // JsBackend implementation. - virtual void SetParentJsEventRouter(JsEventRouter* router); - virtual void RemoveParentJsEventRouter(); - virtual const JsEventRouter* GetParentJsEventRouter() const; + virtual void SetParentJsEventRouter(JsEventRouter* router) OVERRIDE; + virtual void RemoveParentJsEventRouter() OVERRIDE; + virtual const JsEventRouter* GetParentJsEventRouter() const OVERRIDE; virtual void ProcessMessage(const std::string& name, const JsArgList& args, - const JsEventHandler* sender); + const JsEventHandler* sender) OVERRIDE; // JsEventRouter implementation. virtual void RouteJsEvent(const std::string& event_name, - const JsArgList& args, - const JsEventHandler* dst); + const JsArgList& args) OVERRIDE; + virtual void RouteJsMessageReply(const std::string& event_name, + const JsArgList& args, + const JsEventHandler* target) OVERRIDE; struct DoInitializeOptions { DoInitializeOptions( @@ -485,8 +488,11 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar { void HandleInitalizationCompletedOnFrontendLoop(); void RouteJsEventOnFrontendLoop( + const std::string& name, const JsArgList& args); + + void RouteJsMessageReplyOnFrontendLoop( const std::string& name, const JsArgList& args, - const JsEventHandler* dst); + const JsEventHandler* target); void FinishConfigureDataTypesOnFrontendLoop(); diff --git a/chrome/browser/sync/js_event_handler.h b/chrome/browser/sync/js_event_handler.h index 0e8b301..058df9e 100644 --- a/chrome/browser/sync/js_event_handler.h +++ b/chrome/browser/sync/js_event_handler.h @@ -21,6 +21,9 @@ class JsEventHandler { virtual void HandleJsEvent( const std::string& name, const JsArgList& args) = 0; + virtual void HandleJsMessageReply( + const std::string& name, const JsArgList& args) = 0; + protected: virtual ~JsEventHandler() {} }; diff --git a/chrome/browser/sync/js_event_handler_list.cc b/chrome/browser/sync/js_event_handler_list.cc index abc619385..3629fb2 100644 --- a/chrome/browser/sync/js_event_handler_list.cc +++ b/chrome/browser/sync/js_event_handler_list.cc @@ -76,18 +76,19 @@ void JsEventHandlerList::ProcessMessage( } void JsEventHandlerList::RouteJsEvent(const std::string& name, - const JsArgList& args, - const JsEventHandler* target) { - if (target) { - JsEventHandler* non_const_target(const_cast<JsEventHandler*>(target)); - if (handlers_.HasObserver(non_const_target)) { - non_const_target->HandleJsEvent(name, args); - } else { - VLOG(1) << "Unknown target; dropping event " << name - << " with args " << args.ToString(); - } + const JsArgList& args) { + FOR_EACH_OBSERVER(JsEventHandler, handlers_, HandleJsEvent(name, args)); +} + +void JsEventHandlerList::RouteJsMessageReply(const std::string& name, + const JsArgList& args, + const JsEventHandler* target) { + JsEventHandler* non_const_target(const_cast<JsEventHandler*>(target)); + if (handlers_.HasObserver(non_const_target)) { + non_const_target->HandleJsMessageReply(name, args); } else { - FOR_EACH_OBSERVER(JsEventHandler, handlers_, HandleJsEvent(name, args)); + VLOG(1) << "Unknown target; dropping message reply " << name + << " with args " << args.ToString(); } } diff --git a/chrome/browser/sync/js_event_handler_list.h b/chrome/browser/sync/js_event_handler_list.h index 2d5cf9e..a1f0946 100644 --- a/chrome/browser/sync/js_event_handler_list.h +++ b/chrome/browser/sync/js_event_handler_list.h @@ -10,6 +10,7 @@ #include <vector> #include "base/basictypes.h" +#include "base/compiler_specific.h" #include "base/observer_list.h" #include "chrome/browser/sync/js_arg_list.h" #include "chrome/browser/sync/js_event_router.h" @@ -38,17 +39,19 @@ class JsEventHandlerList : public JsFrontend, public JsEventRouter { // JsFrontend implementation. Routes messages to any attached // backend; if there is none, queues up the message for processing // when the next backend is attached. - virtual void AddHandler(JsEventHandler* handler); - virtual void RemoveHandler(JsEventHandler* handler); + virtual void AddHandler(JsEventHandler* handler) OVERRIDE; + virtual void RemoveHandler(JsEventHandler* handler) OVERRIDE; virtual void ProcessMessage( const std::string& name, const JsArgList& args, - const JsEventHandler* sender); + const JsEventHandler* sender) OVERRIDE; // JsEventRouter implementation. Routes the event to the // appropriate handler(s). virtual void RouteJsEvent(const std::string& name, - const JsArgList& args, - const JsEventHandler* target); + const JsArgList& args) OVERRIDE; + virtual void RouteJsMessageReply(const std::string& name, + const JsArgList& args, + const JsEventHandler* target) OVERRIDE; private: // A struct used to hold the arguments to ProcessMessage() for diff --git a/chrome/browser/sync/js_event_handler_list_unittest.cc b/chrome/browser/sync/js_event_handler_list_unittest.cc index 449e70f..fee0dc3 100644 --- a/chrome/browser/sync/js_event_handler_list_unittest.cc +++ b/chrome/browser/sync/js_event_handler_list_unittest.cc @@ -37,13 +37,13 @@ TEST_F(JsEventHandlerListTest, Basic) { EXPECT_CALL(backend, ProcessMessage("test1", HasArgs(args2), &handler1)); EXPECT_CALL(backend, ProcessMessage("test2", HasArgs(args1), &handler2)); - EXPECT_CALL(handler1, HandleJsEvent("reply1", HasArgs(args2))); - EXPECT_CALL(handler1, HandleJsEvent("allreply", HasArgs(args1))); + EXPECT_CALL(handler1, HandleJsMessageReply("reply1", HasArgs(args2))); + EXPECT_CALL(handler1, HandleJsEvent("event", HasArgs(args1))); - EXPECT_CALL(handler2, HandleJsEvent("reply2", HasArgs(args1))); - EXPECT_CALL(handler2, HandleJsEvent("allreply", HasArgs(args1))); - EXPECT_CALL(handler2, HandleJsEvent("anotherreply2", HasArgs(args2))); - EXPECT_CALL(handler2, HandleJsEvent("anotherallreply", HasArgs(args2))); + EXPECT_CALL(handler2, HandleJsMessageReply("reply2", HasArgs(args1))); + EXPECT_CALL(handler2, HandleJsEvent("event", HasArgs(args1))); + EXPECT_CALL(handler2, HandleJsMessageReply("anotherreply2", HasArgs(args2))); + EXPECT_CALL(handler2, HandleJsEvent("anotherevent", HasArgs(args2))); event_handlers.SetBackend(&backend); @@ -52,23 +52,25 @@ TEST_F(JsEventHandlerListTest, Basic) { event_handlers.ProcessMessage("test1", args2, &handler1); - event_handlers.RouteJsEvent("reply2", args1, &handler2); - event_handlers.RouteJsEvent("reply1", args2, &handler1); - event_handlers.RouteJsEvent("allreply", args1, NULL); + event_handlers.RouteJsMessageReply("reply2", args1, &handler2); + event_handlers.RouteJsMessageReply("reply1", args2, &handler1); + event_handlers.RouteJsEvent("event", args1); event_handlers.RemoveHandler(&handler1); event_handlers.ProcessMessage("test2", args1, &handler2); - event_handlers.RouteJsEvent("droppedreply1", args1, &handler1); - event_handlers.RouteJsEvent("anotherreply2", args2, &handler2); - event_handlers.RouteJsEvent("anotherallreply", args2, NULL); + event_handlers.RouteJsMessageReply("droppedreply1", args1, &handler1); + event_handlers.RouteJsMessageReply("anotherreply2", args2, &handler2); + event_handlers.RouteJsEvent("anotherevent", args2); event_handlers.RemoveHandler(&handler2); - event_handlers.RouteJsEvent("anotherdroppedreply1", args1, &handler1); - event_handlers.RouteJsEvent("anotheranotherreply2", args2, &handler2); - event_handlers.RouteJsEvent("droppedallreply", args2, NULL); + event_handlers.RouteJsMessageReply("anotherdroppedreply1", + args1, &handler1); + event_handlers.RouteJsMessageReply("anotheranotherreply2", + args2, &handler2); + event_handlers.RouteJsEvent("droppedevent", args2); // Let destructor of |event_handlers| call RemoveBackend(). } diff --git a/chrome/browser/sync/js_event_router.h b/chrome/browser/sync/js_event_router.h index be783f4..9fad052 100644 --- a/chrome/browser/sync/js_event_router.h +++ b/chrome/browser/sync/js_event_router.h @@ -20,13 +20,15 @@ class JsEventHandler; // JsEventRouters. class JsEventRouter { public: - // If |target| is NULL that means the event is intended for every - // handler. Otherwise the event is meant for the given target only. + virtual void RouteJsEvent( + const std::string& name, const JsArgList& args) = 0; + // |target| is const because it shouldn't be used except by the // router that directly knows about it (which can then safely cast // away the constness). - virtual void RouteJsEvent(const std::string& name, const JsArgList& args, - const JsEventHandler* target) = 0; + virtual void RouteJsMessageReply( + const std::string& name, const JsArgList& args, + const JsEventHandler* target) = 0; protected: virtual ~JsEventRouter() {} diff --git a/chrome/browser/sync/js_sync_manager_observer.cc b/chrome/browser/sync/js_sync_manager_observer.cc index a86178a..a58c586 100644 --- a/chrome/browser/sync/js_sync_manager_observer.cc +++ b/chrome/browser/sync/js_sync_manager_observer.cc @@ -35,8 +35,7 @@ void JsSyncManagerObserver::OnChangesApplied( for (int i = 0; i < change_count; ++i) { change_values->Append(changes[i].ToValue(trans)); } - parent_router_->RouteJsEvent("onChangesApplied", - JsArgList(return_args), NULL); + parent_router_->RouteJsEvent("onChangesApplied", JsArgList(return_args)); } void JsSyncManagerObserver::OnChangesComplete( @@ -44,31 +43,27 @@ void JsSyncManagerObserver::OnChangesComplete( ListValue return_args; return_args.Append(Value::CreateStringValue( syncable::ModelTypeToString(model_type))); - parent_router_->RouteJsEvent("onChangesComplete", - JsArgList(return_args), NULL); + parent_router_->RouteJsEvent("onChangesComplete", JsArgList(return_args)); } void JsSyncManagerObserver::OnSyncCycleCompleted( const sessions::SyncSessionSnapshot* snapshot) { ListValue return_args; return_args.Append(snapshot->ToValue()); - parent_router_->RouteJsEvent("onSyncCycleCompleted", - JsArgList(return_args), NULL); + parent_router_->RouteJsEvent("onSyncCycleCompleted", JsArgList(return_args)); } void JsSyncManagerObserver::OnAuthError( const GoogleServiceAuthError& auth_error) { ListValue return_args; return_args.Append(auth_error.ToValue()); - parent_router_->RouteJsEvent("onAuthError", - JsArgList(return_args), NULL); + parent_router_->RouteJsEvent("onAuthError", JsArgList(return_args)); } void JsSyncManagerObserver::OnUpdatedToken(const std::string& token) { ListValue return_args; return_args.Append(Value::CreateStringValue("<redacted>")); - parent_router_->RouteJsEvent("onUpdatedToken", - JsArgList(return_args), NULL); + parent_router_->RouteJsEvent("onUpdatedToken", JsArgList(return_args)); } void JsSyncManagerObserver::OnPassphraseRequired( @@ -78,7 +73,7 @@ void JsSyncManagerObserver::OnPassphraseRequired( return_args.Append(Value::CreateStringValue( sync_api::PassphraseRequiredReasonToString(reason))); parent_router_->RouteJsEvent("onPassphraseRequired", - JsArgList(return_args), NULL); + JsArgList(return_args)); } void JsSyncManagerObserver::OnPassphraseAccepted( @@ -86,7 +81,7 @@ void JsSyncManagerObserver::OnPassphraseAccepted( ListValue return_args; return_args.Append(Value::CreateStringValue("<redacted>")); parent_router_->RouteJsEvent("onPassphraseAccepted", - JsArgList(return_args), NULL); + JsArgList(return_args)); } void JsSyncManagerObserver::OnEncryptionComplete( @@ -94,7 +89,7 @@ void JsSyncManagerObserver::OnEncryptionComplete( ListValue return_args; return_args.Append(syncable::ModelTypeSetToValue(encrypted_types)); parent_router_->RouteJsEvent("onEncryptionComplete", - JsArgList(return_args), NULL); + JsArgList(return_args)); } void JsSyncManagerObserver::OnMigrationNeededForTypes( @@ -102,27 +97,23 @@ void JsSyncManagerObserver::OnMigrationNeededForTypes( ListValue return_args; return_args.Append(syncable::ModelTypeSetToValue(types)); parent_router_->RouteJsEvent("onMigrationNeededForTypes", - JsArgList(return_args), NULL); - // TODO(akalin): Bug 79247. Hook up JS boiler plate! + JsArgList(return_args)); } void JsSyncManagerObserver::OnInitializationComplete() { - parent_router_->RouteJsEvent("onInitializationComplete", - JsArgList(), NULL); + parent_router_->RouteJsEvent("onInitializationComplete", JsArgList()); } void JsSyncManagerObserver::OnStopSyncingPermanently() { - parent_router_->RouteJsEvent("onStopSyncingPermanently", - JsArgList(), NULL); + parent_router_->RouteJsEvent("onStopSyncingPermanently", JsArgList()); } void JsSyncManagerObserver::OnClearServerDataSucceeded() { - parent_router_->RouteJsEvent("onClearServerDataSucceeded", - JsArgList(), NULL); + parent_router_->RouteJsEvent("onClearServerDataSucceeded", JsArgList()); } void JsSyncManagerObserver::OnClearServerDataFailed() { - parent_router_->RouteJsEvent("onClearServerDataFailed", JsArgList(), NULL); + parent_router_->RouteJsEvent("onClearServerDataFailed", JsArgList()); } } // namespace browser_sync diff --git a/chrome/browser/sync/js_sync_manager_observer_unittest.cc b/chrome/browser/sync/js_sync_manager_observer_unittest.cc index 8a15cca..000c433 100644 --- a/chrome/browser/sync/js_sync_manager_observer_unittest.cc +++ b/chrome/browser/sync/js_sync_manager_observer_unittest.cc @@ -35,16 +35,16 @@ TEST_F(JsSyncManagerObserverTest, NoArgNotifiations) { EXPECT_CALL(mock_router_, RouteJsEvent("onInitializationComplete", - HasArgs(JsArgList()), NULL)); + HasArgs(JsArgList()))); EXPECT_CALL(mock_router_, RouteJsEvent("onStopSyncingPermanently", - HasArgs(JsArgList()), NULL)); + HasArgs(JsArgList()))); EXPECT_CALL(mock_router_, RouteJsEvent("onClearServerDataSucceeded", - HasArgs(JsArgList()), NULL)); + HasArgs(JsArgList()))); EXPECT_CALL(mock_router_, RouteJsEvent("onClearServerDataFailed", - HasArgs(JsArgList()), NULL)); + HasArgs(JsArgList()))); sync_manager_observer_.OnInitializationComplete(); sync_manager_observer_.OnStopSyncingPermanently(); @@ -63,7 +63,7 @@ TEST_F(JsSyncManagerObserverTest, OnChangesComplete) { expected_args.Append(Value::CreateStringValue(model_type_str)); EXPECT_CALL(mock_router_, RouteJsEvent("onChangesComplete", - HasArgsAsList(expected_args), NULL)); + HasArgsAsList(expected_args))); } for (int i = syncable::FIRST_REAL_MODEL_TYPE; @@ -92,7 +92,7 @@ TEST_F(JsSyncManagerObserverTest, OnSyncCycleCompleted) { EXPECT_CALL(mock_router_, RouteJsEvent("onSyncCycleCompleted", - HasArgsAsList(expected_args), NULL)); + HasArgsAsList(expected_args))); sync_manager_observer_.OnSyncCycleCompleted(&snapshot); } @@ -104,7 +104,7 @@ TEST_F(JsSyncManagerObserverTest, OnAuthError) { EXPECT_CALL(mock_router_, RouteJsEvent("onAuthError", - HasArgsAsList(expected_args), NULL)); + HasArgsAsList(expected_args))); sync_manager_observer_.OnAuthError(error); } @@ -129,19 +129,18 @@ TEST_F(JsSyncManagerObserverTest, OnPassphraseRequired) { sync_api::REASON_SET_PASSPHRASE_FAILED))); EXPECT_CALL(mock_router_, - RouteJsEvent("onPassphraseRequired", - HasArgsAsList(reason_passphrase_not_required_args), - NULL)); + RouteJsEvent( + "onPassphraseRequired", + HasArgsAsList(reason_passphrase_not_required_args))); EXPECT_CALL(mock_router_, RouteJsEvent("onPassphraseRequired", - HasArgsAsList(reason_encryption_args), NULL)); + HasArgsAsList(reason_encryption_args))); EXPECT_CALL(mock_router_, RouteJsEvent("onPassphraseRequired", - HasArgsAsList(reason_decryption_args), NULL)); + HasArgsAsList(reason_decryption_args))); EXPECT_CALL(mock_router_, RouteJsEvent("onPassphraseRequired", - HasArgsAsList(reason_set_passphrase_failed_args), - NULL)); + HasArgsAsList(reason_set_passphrase_failed_args))); sync_manager_observer_.OnPassphraseRequired( sync_api::REASON_PASSPHRASE_NOT_REQUIRED); @@ -157,10 +156,10 @@ TEST_F(JsSyncManagerObserverTest, SensitiveNotifiations) { EXPECT_CALL(mock_router_, RouteJsEvent("onUpdatedToken", - HasArgsAsList(redacted_args), NULL)); + HasArgsAsList(redacted_args))); EXPECT_CALL(mock_router_, RouteJsEvent("onPassphraseAccepted", - HasArgsAsList(redacted_args), NULL)); + HasArgsAsList(redacted_args))); sync_manager_observer_.OnUpdatedToken("sensitive_token"); sync_manager_observer_.OnPassphraseAccepted("sensitive_token"); @@ -182,7 +181,7 @@ TEST_F(JsSyncManagerObserverTest, OnEncryptionComplete) { EXPECT_CALL(mock_router_, RouteJsEvent("onEncryptionComplete", - HasArgsAsList(expected_args), NULL)); + HasArgsAsList(expected_args))); sync_manager_observer_.OnEncryptionComplete(encrypted_types); } @@ -203,7 +202,7 @@ TEST_F(JsSyncManagerObserverTest, OnMigrationNeededForTypes) { EXPECT_CALL(mock_router_, RouteJsEvent("onMigrationNeededForTypes", - HasArgsAsList(expected_args), NULL)); + HasArgsAsList(expected_args))); sync_manager_observer_.OnMigrationNeededForTypes(types); } @@ -281,7 +280,7 @@ TEST_F(JsSyncManagerObserverTest, OnChangesApplied) { } EXPECT_CALL(mock_router_, RouteJsEvent("onChangesApplied", - HasArgsAsList(expected_args), NULL)); + HasArgsAsList(expected_args))); } // Fire OnChangesApplied() for each data type. diff --git a/chrome/browser/sync/js_test_util.h b/chrome/browser/sync/js_test_util.h index 23a8dad..85b4fc7 100644 --- a/chrome/browser/sync/js_test_util.h +++ b/chrome/browser/sync/js_test_util.h @@ -65,6 +65,8 @@ class MockJsEventHandler : public JsEventHandler { ~MockJsEventHandler(); MOCK_METHOD2(HandleJsEvent, void(const ::std::string&, const JsArgList&)); + MOCK_METHOD2(HandleJsMessageReply, + void(const ::std::string&, const JsArgList&)); }; class MockJsEventRouter : public JsEventRouter { @@ -72,7 +74,9 @@ class MockJsEventRouter : public JsEventRouter { MockJsEventRouter(); ~MockJsEventRouter(); - MOCK_METHOD3(RouteJsEvent, + MOCK_METHOD2(RouteJsEvent, + void(const ::std::string&, const JsArgList&)); + MOCK_METHOD3(RouteJsMessageReply, void(const ::std::string&, const JsArgList&, const JsEventHandler*)); }; diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc index 9d898cd..5a31625 100644 --- a/chrome/browser/sync/profile_sync_service.cc +++ b/chrome/browser/sync/profile_sync_service.cc @@ -429,7 +429,7 @@ void ProfileSyncService::NotifyObservers() { // TODO(akalin): Make an Observer subclass that listens and does the // event routing. js_event_handlers_.RouteJsEvent( - "onSyncServiceStateChanged", browser_sync::JsArgList(), NULL); + "onSyncServiceStateChanged", browser_sync::JsArgList()); } // static diff --git a/chrome/browser/sync/profile_sync_service_unittest.cc b/chrome/browser/sync/profile_sync_service_unittest.cc index e170e1d..69502a7 100644 --- a/chrome/browser/sync/profile_sync_service_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_unittest.cc @@ -222,14 +222,15 @@ TEST_F(ProfileSyncServiceTest, JsFrontendProcessMessageBasic) { arg_list1.Append(Value::CreateBooleanValue(true)); arg_list1.Append(Value::CreateIntegerValue(5)); JsArgList args1(arg_list1); - EXPECT_CALL(event_handler, HandleJsEvent("testMessage1", HasArgs(args1))); + EXPECT_CALL(event_handler, + HandleJsMessageReply("testMessage1", HasArgs(args1))); ListValue arg_list2; arg_list2.Append(Value::CreateStringValue("test")); arg_list2.Append(arg_list1.DeepCopy()); JsArgList args2(arg_list2); EXPECT_CALL(event_handler, - HandleJsEvent("delayTestMessage2", HasArgs(args2))); + HandleJsMessageReply("delayTestMessage2", HasArgs(args2))); ListValue arg_list3; arg_list3.Append(arg_list1.DeepCopy()); @@ -280,20 +281,22 @@ TEST_F(ProfileSyncServiceTest, arg_list1.Append(Value::CreateBooleanValue(true)); arg_list1.Append(Value::CreateIntegerValue(5)); JsArgList args1(arg_list1); - EXPECT_CALL(event_handler, HandleJsEvent("testMessage1", HasArgs(args1))); + EXPECT_CALL(event_handler, + HandleJsMessageReply("testMessage1", HasArgs(args1))); ListValue arg_list2; arg_list2.Append(Value::CreateStringValue("test")); arg_list2.Append(arg_list1.DeepCopy()); JsArgList args2(arg_list2); - EXPECT_CALL(event_handler, HandleJsEvent("testMessage2", HasArgs(args2))); + EXPECT_CALL(event_handler, + HandleJsMessageReply("testMessage2", HasArgs(args2))); ListValue arg_list3; arg_list3.Append(arg_list1.DeepCopy()); arg_list3.Append(arg_list2.DeepCopy()); JsArgList args3(arg_list3); EXPECT_CALL(event_handler, - HandleJsEvent("delayTestMessage3", HasArgs(args3))); + HandleJsMessageReply("delayTestMessage3", HasArgs(args3))); const JsArgList kNoArgs; diff --git a/chrome/browser/sync/test_profile_sync_service.cc b/chrome/browser/sync/test_profile_sync_service.cc index 0a2b7bc..337b555 100644 --- a/chrome/browser/sync/test_profile_sync_service.cc +++ b/chrome/browser/sync/test_profile_sync_service.cc @@ -122,9 +122,9 @@ void SyncBackendHostForProfileSyncTest::ProcessMessage( const std::string& name, const JsArgList& args, const JsEventHandler* sender) { if (name.find("delay") != name.npos) { - core_->RouteJsEvent(name, args, sender); + core_->RouteJsMessageReply(name, args, sender); } else { - core_->RouteJsEventOnFrontendLoop(name, args, sender); + core_->RouteJsMessageReplyOnFrontendLoop(name, args, sender); } } diff --git a/chrome/browser/sync/test_profile_sync_service.h b/chrome/browser/sync/test_profile_sync_service.h index d07e777..4c3e19d 100644 --- a/chrome/browser/sync/test_profile_sync_service.h +++ b/chrome/browser/sync/test_profile_sync_service.h @@ -8,6 +8,7 @@ #include <string> +#include "base/compiler_specific.h" #include "chrome/browser/sync/glue/data_type_manager_impl.h" #include "chrome/browser/sync/js_backend.h" #include "chrome/browser/sync/profile_sync_service.h" @@ -60,14 +61,14 @@ class SyncBackendHostForProfileSyncTest virtual JsBackend* GetJsBackend(); // JsBackend implementation. - virtual void SetParentJsEventRouter(JsEventRouter* router); - virtual void RemoveParentJsEventRouter(); - virtual const JsEventRouter* GetParentJsEventRouter() const; + virtual void SetParentJsEventRouter(JsEventRouter* router) OVERRIDE; + virtual void RemoveParentJsEventRouter() OVERRIDE; + virtual const JsEventRouter* GetParentJsEventRouter() const OVERRIDE; // Fires an event identical to the message unless the message has // "delay" as a prefix, in which case a task to fire the identical // event is posted instead. virtual void ProcessMessage(const std::string& name, const JsArgList& args, - const JsEventHandler* sender); + const JsEventHandler* sender) OVERRIDE; virtual void StartConfiguration(Callback0::Type* callback); diff --git a/chrome/browser/ui/webui/sync_internals_ui.cc b/chrome/browser/ui/webui/sync_internals_ui.cc index e11eb23..e1f88af 100644 --- a/chrome/browser/ui/webui/sync_internals_ui.cc +++ b/chrome/browser/ui/webui/sync_internals_ui.cc @@ -56,8 +56,7 @@ void SyncInternalsUI::OnWebUISend(const GURL& source_url, args.Append(about_info); ProfileSyncService* service = GetProfile()->GetProfileSyncService(); sync_ui_util::ConstructAboutInformation(service, about_info); - HandleJsEvent("onGetAboutInfoFinished", - browser_sync::JsArgList(args)); + HandleJsMessageReply(name, browser_sync::JsArgList(args)); } else { browser_sync::JsFrontend* backend = GetJsFrontend(); if (backend) { @@ -72,8 +71,19 @@ void SyncInternalsUI::OnWebUISend(const GURL& source_url, void SyncInternalsUI::HandleJsEvent(const std::string& name, const browser_sync::JsArgList& args) { VLOG(1) << "Handling event: " << name << " with args " << args.ToString(); + const std::string& event_handler = "chrome.sync." + name + ".fire"; std::vector<const Value*> arg_list(args.Get().begin(), args.Get().end()); - CallJavascriptFunction(name, arg_list); + CallJavascriptFunction(event_handler, arg_list); +} + +void SyncInternalsUI::HandleJsMessageReply( + const std::string& name, + const browser_sync::JsArgList& args) { + VLOG(1) << "Handling reply for " << name << " message with args " + << args.ToString(); + const std::string& reply_handler = "chrome.sync." + name + ".handleReply"; + std::vector<const Value*> arg_list(args.Get().begin(), args.Get().end()); + CallJavascriptFunction(reply_handler, arg_list); } browser_sync::JsFrontend* SyncInternalsUI::GetJsFrontend() { diff --git a/chrome/browser/ui/webui/sync_internals_ui.h b/chrome/browser/ui/webui/sync_internals_ui.h index e5a8118..6512fca 100644 --- a/chrome/browser/ui/webui/sync_internals_ui.h +++ b/chrome/browser/ui/webui/sync_internals_ui.h @@ -43,6 +43,9 @@ class SyncInternalsUI : public WebUI, public browser_sync::JsEventHandler { // browser_sync::JsEventHandler implementation. virtual void HandleJsEvent(const std::string& name, const browser_sync::JsArgList& args) OVERRIDE; + virtual void HandleJsMessageReply( + const std::string& name, + const browser_sync::JsArgList& args) OVERRIDE; private: // Returns the sync service's JsFrontend object, or NULL if the sync diff --git a/chrome/browser/ui/webui/sync_internals_ui_unittest.cc b/chrome/browser/ui/webui/sync_internals_ui_unittest.cc index 1c0068c..0ae2436 100644 --- a/chrome/browser/ui/webui/sync_internals_ui_unittest.cc +++ b/chrome/browser/ui/webui/sync_internals_ui_unittest.cc @@ -138,7 +138,8 @@ TEST_F(SyncInternalsUITest, HandleJsEvent) { ConstructTestSyncInternalsUI(); EXPECT_CALL(*GetTestSyncInternalsUI(), - ExecuteJavascript(ASCIIToUTF16("testMessage(5,true);"))); + ExecuteJavascript( + ASCIIToUTF16("chrome.sync.testMessage.fire(5,true);"))); ListValue args; args.Append(Value::CreateIntegerValue(5)); @@ -152,7 +153,8 @@ TEST_F(SyncInternalsUITest, HandleJsEventNullService) { ConstructTestSyncInternalsUI(); EXPECT_CALL(*GetTestSyncInternalsUI(), - ExecuteJavascript(ASCIIToUTF16("testMessage(5,true);"))); + ExecuteJavascript( + ASCIIToUTF16("chrome.sync.testMessage.fire(5,true);"))); ListValue args; args.Append(Value::CreateIntegerValue(5)); @@ -160,6 +162,40 @@ TEST_F(SyncInternalsUITest, HandleJsEventNullService) { GetTestSyncInternalsUI()->HandleJsEvent("testMessage", JsArgList(args)); } +TEST_F(SyncInternalsUITest, HandleJsMessageReply) { + ExpectSetupTeardownCalls(); + + ConstructTestSyncInternalsUI(); + + EXPECT_CALL( + *GetTestSyncInternalsUI(), + ExecuteJavascript( + ASCIIToUTF16("chrome.sync.testMessage.handleReply(5,true);"))); + + ListValue args; + args.Append(Value::CreateIntegerValue(5)); + args.Append(Value::CreateBooleanValue(true)); + GetTestSyncInternalsUI()->HandleJsMessageReply( + "testMessage", JsArgList(args)); +} + +TEST_F(SyncInternalsUITest, HandleJsMessageReplyNullService) { + ExpectSetupTeardownCallsNullService(); + + ConstructTestSyncInternalsUI(); + + EXPECT_CALL( + *GetTestSyncInternalsUI(), + ExecuteJavascript( + ASCIIToUTF16("chrome.sync.testMessage.handleReply(5,true);"))); + + ListValue args; + args.Append(Value::CreateIntegerValue(5)); + args.Append(Value::CreateBooleanValue(true)); + GetTestSyncInternalsUI()->HandleJsMessageReply( + "testMessage", JsArgList(args)); +} + TEST_F(SyncInternalsUITest, OnWebUISendBasic) { ExpectSetupTeardownCalls(); @@ -191,7 +227,7 @@ TEST_F(SyncInternalsUITest, OnWebUISendBasicNullService) { namespace { const char kAboutInfoCall[] = - "onGetAboutInfoFinished({\"summary\":\"SYNC DISABLED\"});"; + "chrome.sync.getAboutInfo.handleReply({\"summary\":\"SYNC DISABLED\"});"; } // namespace // TODO(lipalani) - add a test case to test about:sync with a non null service. |