diff options
author | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-10 09:23:39 +0000 |
---|---|---|
committer | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-10 09:23:39 +0000 |
commit | ec5263a0914ca9f58586f3808b1ab45acd3b9400 (patch) | |
tree | 9e119d6b7578eb6ab348fd4334c5bd9c818f0bbe | |
parent | 46be25eca97a31cae1b48a59513591f32d0ce6b4 (diff) | |
download | chromium_src-ec5263a0914ca9f58586f3808b1ab45acd3b9400.zip chromium_src-ec5263a0914ca9f58586f3808b1ab45acd3b9400.tar.gz chromium_src-ec5263a0914ca9f58586f3808b1ab45acd3b9400.tar.bz2 |
[Sync] Remove more boilerplate from chrome://sync-internals js files
Add new JsEventDetails class which encapsulates a DictionaryValue.
Make JS events use that instead of JsArgList.
Automate listening to log events in sync_log.js.
Cleaned up javascript files a bit.
Add Swap() method to DictionaryValue.
BUG=
TEST=
Review URL: http://codereview.chromium.org/6951009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@84767 0039d316-1c4b-4281-b951-d872f2087c98
33 files changed, 488 insertions, 334 deletions
diff --git a/base/values.h b/base/values.h index 49ac219..6fb3240 100644 --- a/base/values.h +++ b/base/values.h @@ -308,6 +308,11 @@ class BASE_API DictionaryValue : public Value { // replaced. void MergeDictionary(const DictionaryValue* dictionary); + // Swaps contents with the |other| dictionary. + void Swap(DictionaryValue* other) { + dictionary_.swap(other->dictionary_); + } + // This class provides an iterator for the keys in the dictionary. // It can't be used to modify the dictionary. // diff --git a/chrome/browser/resources/sync_internals/about.html b/chrome/browser/resources/sync_internals/about.html index 9f9451d..2fd4a36 100644 --- a/chrome/browser/resources/sync_internals/about.html +++ b/chrome/browser/resources/sync_internals/about.html @@ -13,7 +13,7 @@ function refreshAboutInfo(aboutInfo) { function onLoad() { chrome.sync.getAboutInfo(refreshAboutInfo); - chrome.sync.onSyncServiceStateChanged.addListener(function() { + chrome.sync.onServiceStateChanged.addListener(function() { chrome.sync.getAboutInfo(refreshAboutInfo); }); } diff --git a/chrome/browser/resources/sync_internals/chrome_sync.js b/chrome/browser/resources/sync_internals/chrome_sync.js index 8d2dcbf..b8bf08a 100644 --- a/chrome/browser/resources/sync_internals/chrome_sync.js +++ b/chrome/browser/resources/sync_internals/chrome_sync.js @@ -62,38 +62,44 @@ Event.prototype.fire = function() { } }; -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' -]; +chrome.sync.events = { + 'service': [ + 'onServiceStateChanged' + ], + + 'notifier': [ + 'onNotificationStateChange', + 'onIncomingNotification' + ], + + 'manager': [ + '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(); +for (var eventType in chrome.sync.events) { + var events = chrome.sync.events[eventType]; + for (var i = 0; i < events.length; ++i) { + var event = events[i]; + chrome.sync[event] = new Event(); + } } -function makeAsyncFunction(name) { +function makeSyncFunction(name) { var callbacks = []; // Calls the function, assuming the last argument is a callback to be @@ -133,7 +139,7 @@ var syncFunctions = [ for (var i = 0; i < syncFunctions.length; ++i) { var syncFunction = syncFunctions[i]; - chrome.sync[syncFunction] = makeAsyncFunction(syncFunction); + chrome.sync[syncFunction] = makeSyncFunction(syncFunction); } })(); diff --git a/chrome/browser/resources/sync_internals/notifications.html b/chrome/browser/resources/sync_internals/notifications.html index 5f8d31a8..dccc68c 100644 --- a/chrome/browser/resources/sync_internals/notifications.html +++ b/chrome/browser/resources/sync_internals/notifications.html @@ -15,20 +15,21 @@ function updateNotificationsEnabledInfo(notificationsEnabled) { function updateNotificationInfo(notification) { var notificationInfo = document.getElementById('notificationInfo'); - jstProcess( - new JsEvalContext({ 'notificationInfo': - JSON.stringify(notification, null, 2) - }), - notificationInfo); + jstProcess( + new JsEvalContext({ + 'notificationInfo': JSON.stringify(notification, null, 2) + }), + notificationInfo); } function onLoad() { chrome.sync.getNotificationState(updateNotificationsEnabledInfo); chrome.sync.getNotificationInfo(updateNotificationInfo); - chrome.sync.onSyncNotificationStateChange.addListener( - updateNotificationsEnabledInfo); + chrome.sync.onNotificationStateChange.addListener( + function(details) { updateNotificationsEnabledInfo(details.enabled); }); - chrome.sync.onSyncIncomingNotification.addListener(function(changedTypes) { + chrome.sync.onIncomingNotification.addListener(function(details) { + var changedTypes = details.changedTypes; for (var i = 0; i < changedTypes.length; ++i) { var changedType = changedTypes[i]; chrome.sync.notifications[changedType] = @@ -66,9 +67,7 @@ table#notificationsInfo tr:nth-child(odd) { <p id='notificationsEnabledInfo'> Enabled: <span jscontent='notificationsEnabled'></span> </p> -<p id='notificationInfo'> - <span jscontent='notificationInfo'></span> -</p> +<pre id='notificationInfo'><span jscontent='notificationInfo'></span></pre> <table id='notificationsInfo'> <tr jsselect='notifications'> <td jscontent='modelType'/> diff --git a/chrome/browser/resources/sync_internals/sync_log.js b/chrome/browser/resources/sync_internals/sync_log.js index 35a6f2f..6d10e4e 100644 --- a/chrome/browser/resources/sync_internals/sync_log.js +++ b/chrome/browser/resources/sync_internals/sync_log.js @@ -21,107 +21,20 @@ cr.define('chrome.sync', function() { var Log = function() { var self = this; - // Service - - chrome.sync.onSyncServiceStateChanged.addListener(function () { - self.log_('service', 'onSyncServiceStateChanged', {}); - }); - - // Notifier - - chrome.sync.onSyncNotificationStateChange.addListener( - function (notificationsEnabled) { - self.log_('notifier', 'onSyncNotificationStateChange', { - notificationsEnabled: notificationsEnabled - }); - }); - - chrome.sync.onSyncIncomingNotification.addListener(function (changedTypes) { - self.log_('notifier', 'onSyncIncomingNotification', { - changedTypes: changedTypes - }); - }); - - // Manager - - chrome.sync.onChangesApplied.addListener(function (modelType, changes) { - self.log_('manager', 'onChangesApplied', { - modelType: modelType, - changes: changes - }); - }); - - chrome.sync.onChangesComplete.addListener(function (modelType) { - self.log_('manager', 'onChangesComplete', { - modelType: modelType - }); - }); - - chrome.sync.onSyncCycleCompleted.addListener(function (snapshot) { - self.log_('manager', 'onSyncCycleCompleted', { - snapshot: snapshot - }); - }); - - chrome.sync.onAuthError.addListener(function (authError) { - self.log_('manager', 'onAuthError', { - authError: authError - }); - }); - - chrome.sync.onUpdatedToken.addListener(function (token) { - self.log_('manager', 'onUpdatedToken', { - token: token - }); - }); - - chrome.sync.onPassphraseRequired.addListener(function (reason) { - self.log_('manager', 'onPassphraseRequired', { - reason: reason - }); - }); - - chrome.sync.onPassphraseAccepted.addListener(function (bootstrapToken) { - self.log_('manager', 'onPassphraseAccepted', { - bootstrapToken: bootstrapToken - }); - }); - - chrome.sync.onEncryptionComplete.addListener(function (encrypted_types) { - self.log_('manager', 'onEncryptionComplete', { - encrypted_types: encrypted_types - }); - }); - - chrome.sync.onMigrationNeededForTypes.addListener(function (model_types) { - self.log_('manager', 'onMigrationNeededForTypes', { - model_types: model_types - }); - }); - - chrome.sync.onInitializationComplete.addListener(function () { - self.log_('manager', 'onInitializationComplete', {}); - }); - - chrome.sync.onPaused.addListener(function () { - self.log_('manager', 'onPaused', {}); - }); - - chrome.sync.onResumed.addListener(function () { - self.log_('manager', 'onResumed', {}); - }); - - chrome.sync.onStopSyncingPermanently.addListener(function () { - self.log_('manager', 'onStopSyncingPermanently', {}); - }); - - chrome.sync.onClearServerDataSucceeded.addListener(function () { - self.log_('manager', 'onClearServerDataSucceeded', {}); - }); - - chrome.sync.onClearServerDataFailed.addListener(function () { - self.log_('manager', 'onClearServerDataFailed', {}); - }); + var makeListener = function(service, event) { + return function(details) { + self.log_(service, event, details); + }; + }; + + for (var eventType in chrome.sync.events) { + var events = chrome.sync.events[eventType]; + for (var i = 0; i < events.length; ++i) { + var eventName = events[i]; + var event = chrome.sync[eventName]; + event.addListener(makeListener(eventType, eventName)); + } + } }; Log.prototype = { diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc index 44e7024..178bf55 100644 --- a/chrome/browser/sync/engine/syncapi.cc +++ b/chrome/browser/sync/engine/syncapi.cc @@ -38,6 +38,7 @@ #include "chrome/browser/sync/engine/http_post_provider_factory.h" #include "chrome/browser/sync/js_arg_list.h" #include "chrome/browser/sync/js_backend.h" +#include "chrome/browser/sync/js_event_details.h" #include "chrome/browser/sync/js_event_router.h" #include "chrome/browser/sync/notifier/sync_notifier.h" #include "chrome/browser/sync/notifier/sync_notifier_observer.h" @@ -2726,11 +2727,10 @@ void SyncManager::SyncInternal::OnNotificationStateChange( syncer_thread()->set_notifications_enabled(notifications_enabled); } if (parent_router_) { - ListValue args; - args.Append(Value::CreateBooleanValue(notifications_enabled)); - // TODO(akalin): Tidy up grammar in event names. - parent_router_->RouteJsEvent("onSyncNotificationStateChange", - browser_sync::JsArgList(&args)); + DictionaryValue details; + details.Set("enabled", Value::CreateBooleanValue(notifications_enabled)); + parent_router_->RouteJsEvent("onNotificationStateChange", + browser_sync::JsEventDetails(&details)); } } @@ -2760,9 +2760,9 @@ void SyncManager::SyncInternal::OnIncomingNotification( } if (parent_router_) { - ListValue args; + DictionaryValue details; ListValue* changed_types = new ListValue(); - args.Append(changed_types); + details.Set("changedTypes", changed_types); for (syncable::ModelTypePayloadMap::const_iterator it = type_payloads.begin(); it != type_payloads.end(); ++it) { @@ -2770,8 +2770,8 @@ void SyncManager::SyncInternal::OnIncomingNotification( syncable::ModelTypeToString(it->first); changed_types->Append(Value::CreateStringValue(model_type_str)); } - parent_router_->RouteJsEvent("onSyncIncomingNotification", - browser_sync::JsArgList(&args)); + parent_router_->RouteJsEvent("onIncomingNotification", + browser_sync::JsEventDetails(&details)); } } diff --git a/chrome/browser/sync/engine/syncapi.h b/chrome/browser/sync/engine/syncapi.h index 0c181a8..7ccbe03 100644 --- a/chrome/browser/sync/engine/syncapi.h +++ b/chrome/browser/sync/engine/syncapi.h @@ -961,12 +961,12 @@ class SyncManager { // manager). Never returns NULL. The following events are sent by // the returned backend: // - // onSyncNotificationStateChange(boolean notificationsEnabled): + // onNotificationStateChange({ enabled: (boolean) }): // Sent when notifications are enabled or disabled. // - // onSyncIncomingNotification(array changedTypes): + // onIncomingNotification({ changedTypes: (array) }): // Sent when an incoming notification arrives. |changedTypes| - // contains a list of sync types (strings) which have changed. + // is a list of sync types (strings) which have changed. // // The following messages are processed by the returned backend: // diff --git a/chrome/browser/sync/engine/syncapi_unittest.cc b/chrome/browser/sync/engine/syncapi_unittest.cc index c923d5a..56373e4 100644 --- a/chrome/browser/sync/engine/syncapi_unittest.cc +++ b/chrome/browser/sync/engine/syncapi_unittest.cc @@ -44,6 +44,7 @@ using browser_sync::Cryptographer; using browser_sync::HasArgsAsList; +using browser_sync::HasDetailsAsDictionary; using browser_sync::KeyParams; using browser_sync::JsArgList; using browser_sync::MockJsEventHandler; @@ -58,6 +59,7 @@ using test::ExpectDictDictionaryValue; using test::ExpectDictStringValue; using testing::_; using testing::AtLeast; +using testing::InSequence; using testing::Invoke; using testing::SaveArg; using testing::StrictMock; @@ -974,19 +976,20 @@ TEST_F(SyncManagerTest, ProcessMessageGetNodeByIdFailure) { } TEST_F(SyncManagerTest, OnNotificationStateChange) { + InSequence dummy; StrictMock<MockJsEventRouter> event_router; - ListValue true_args; - true_args.Append(Value::CreateBooleanValue(true)); - ListValue false_args; - false_args.Append(Value::CreateBooleanValue(false)); + DictionaryValue true_details; + true_details.SetBoolean("enabled", true); + DictionaryValue false_details; + false_details.SetBoolean("enabled", false); EXPECT_CALL(event_router, - RouteJsEvent("onSyncNotificationStateChange", - HasArgsAsList(true_args))); + RouteJsEvent("onNotificationStateChange", + HasDetailsAsDictionary(true_details))); EXPECT_CALL(event_router, - RouteJsEvent("onSyncNotificationStateChange", - HasArgsAsList(false_args))); + RouteJsEvent("onNotificationStateChange", + HasDetailsAsDictionary(false_details))); browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend(); @@ -1012,10 +1015,10 @@ TEST_F(SyncManagerTest, OnIncomingNotification) { // Build expected_args to have a single argument with the string // equivalents of model_types. - ListValue expected_args; + DictionaryValue expected_details; { ListValue* model_type_list = new ListValue(); - expected_args.Append(model_type_list); + expected_details.Set("changedTypes", model_type_list); for (int i = syncable::FIRST_REAL_MODEL_TYPE; i < syncable::MODEL_TYPE_COUNT; ++i) { if (model_types[i]) { @@ -1028,8 +1031,8 @@ TEST_F(SyncManagerTest, OnIncomingNotification) { } EXPECT_CALL(event_router, - RouteJsEvent("onSyncIncomingNotification", - HasArgsAsList(expected_args))); + RouteJsEvent("onIncomingNotification", + HasDetailsAsDictionary(expected_details))); 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 c3a8bff..92c530a 100644 --- a/chrome/browser/sync/glue/sync_backend_host.cc +++ b/chrome/browser/sync/glue/sync_backend_host.cc @@ -25,6 +25,7 @@ #include "chrome/browser/sync/glue/password_model_worker.h" #include "chrome/browser/sync/glue/sync_backend_host.h" #include "chrome/browser/sync/js_arg_list.h" +#include "chrome/browser/sync/js_event_details.h" #include "chrome/browser/sync/notifier/sync_notifier.h" #include "chrome/browser/sync/notifier/sync_notifier_factory.h" #include "chrome/browser/sync/sessions/session_state.h" @@ -1029,10 +1030,10 @@ void SyncBackendHost::Core::OnEncryptionComplete( } void SyncBackendHost::Core::RouteJsEvent( - const std::string& name, const JsArgList& args) { + const std::string& name, const JsEventDetails& details) { host_->frontend_loop_->PostTask( FROM_HERE, NewRunnableMethod( - this, &Core::RouteJsEventOnFrontendLoop, name, args)); + this, &Core::RouteJsEventOnFrontendLoop, name, details)); } void SyncBackendHost::Core::RouteJsMessageReply( @@ -1074,13 +1075,13 @@ void SyncBackendHost::Core::HandleAuthErrorEventOnFrontendLoop( } void SyncBackendHost::Core::RouteJsEventOnFrontendLoop( - const std::string& name, const JsArgList& args) { + const std::string& name, const JsEventDetails& details) { if (!host_ || !parent_router_) return; DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_); - parent_router_->RouteJsEvent(name, args); + parent_router_->RouteJsEvent(name, details); } void SyncBackendHost::Core::RouteJsMessageReplyOnFrontendLoop( diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h index 6002dae..dac1237 100644 --- a/chrome/browser/sync/glue/sync_backend_host.h +++ b/chrome/browser/sync/glue/sync_backend_host.h @@ -301,7 +301,7 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar { // JsEventRouter implementation. virtual void RouteJsEvent(const std::string& event_name, - const JsArgList& args) OVERRIDE; + const JsEventDetails& details) OVERRIDE; virtual void RouteJsMessageReply(const std::string& event_name, const JsArgList& args, const JsEventHandler* target) OVERRIDE; @@ -488,7 +488,7 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar { void HandleInitalizationCompletedOnFrontendLoop(); void RouteJsEventOnFrontendLoop( - const std::string& name, const JsArgList& args); + const std::string& name, const JsEventDetails& details); void RouteJsMessageReplyOnFrontendLoop( const std::string& name, const JsArgList& args, diff --git a/chrome/browser/sync/js_arg_list.cc b/chrome/browser/sync/js_arg_list.cc index 3695968..73daea0 100644 --- a/chrome/browser/sync/js_arg_list.cc +++ b/chrome/browser/sync/js_arg_list.cc @@ -8,10 +8,10 @@ namespace browser_sync { -JsArgList::JsArgList() : args_(new SharedListValue()) {} +JsArgList::JsArgList() : args_(new SharedValue<ListValue>()) {} JsArgList::JsArgList(ListValue* args) - : args_(new SharedListValue(args)) {} + : args_(new SharedValue<ListValue>(args)) {} JsArgList::~JsArgList() {} @@ -25,16 +25,4 @@ std::string JsArgList::ToString() const { return str; } -JsArgList::SharedListValue::SharedListValue() {} - -JsArgList::SharedListValue::SharedListValue(ListValue* list_value) { - list_value_.Swap(list_value); -} - -const ListValue& JsArgList::SharedListValue::Get() const { - return list_value_; -} - -JsArgList::SharedListValue::~SharedListValue() {} - } // namespace browser_sync diff --git a/chrome/browser/sync/js_arg_list.h b/chrome/browser/sync/js_arg_list.h index 878ec39..3dafa71 100644 --- a/chrome/browser/sync/js_arg_list.h +++ b/chrome/browser/sync/js_arg_list.h @@ -9,10 +9,10 @@ // See README.js for design comments. #include <string> -#include <vector> #include "base/memory/ref_counted.h" #include "base/values.h" +#include "chrome/browser/sync/shared_value.h" namespace browser_sync { @@ -35,21 +35,7 @@ class JsArgList { // Copy constructor and assignment operator welcome. private: - class SharedListValue : public base::RefCountedThreadSafe<SharedListValue> { - public: - SharedListValue(); - explicit SharedListValue(ListValue* list_value); - - const ListValue& Get() const; - - private: - ~SharedListValue(); - friend class base::RefCountedThreadSafe<SharedListValue>; - - ListValue list_value_; - }; - - scoped_refptr<const SharedListValue> args_; + scoped_refptr<const SharedValue<ListValue> > args_; }; } // namespace browser_sync diff --git a/chrome/browser/sync/js_arg_list_unittest.cc b/chrome/browser/sync/js_arg_list_unittest.cc index 5d327c1..ed5c952 100644 --- a/chrome/browser/sync/js_arg_list_unittest.cc +++ b/chrome/browser/sync/js_arg_list_unittest.cc @@ -15,6 +15,7 @@ class JsArgListTest : public testing::Test {}; TEST_F(JsArgListTest, EmptyList) { JsArgList arg_list; EXPECT_TRUE(arg_list.Get().empty()); + EXPECT_EQ("[]", arg_list.ToString()); } TEST_F(JsArgListTest, FromList) { diff --git a/chrome/browser/sync/js_event_details.cc b/chrome/browser/sync/js_event_details.cc new file mode 100644 index 0000000..371716d --- /dev/null +++ b/chrome/browser/sync/js_event_details.cc @@ -0,0 +1,29 @@ +// Copyright (c) 2011 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 "chrome/browser/sync/js_event_details.h" + +#include "base/json/json_writer.h" + +namespace browser_sync { + +JsEventDetails::JsEventDetails() + : details_(new SharedValue<DictionaryValue>()) {} + +JsEventDetails::JsEventDetails(DictionaryValue* details) + : details_(new SharedValue<DictionaryValue>(details)) {} + +JsEventDetails::~JsEventDetails() {} + +const DictionaryValue& JsEventDetails::Get() const { + return details_->Get(); +} + +std::string JsEventDetails::ToString() const { + std::string str; + base::JSONWriter::Write(&Get(), false, &str); + return str; +} + +} // namespace browser_sync diff --git a/chrome/browser/sync/js_event_details.h b/chrome/browser/sync/js_event_details.h new file mode 100644 index 0000000..56129ca --- /dev/null +++ b/chrome/browser/sync/js_event_details.h @@ -0,0 +1,43 @@ +// Copyright (c) 2011 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. + +#ifndef CHROME_BROWSER_SYNC_JS_EVENT_DETAILS_H_ +#define CHROME_BROWSER_SYNC_JS_EVENT_DETAILS_H_ +#pragma once + +// See README.js for design comments. + +#include <string> + +#include "base/memory/ref_counted.h" +#include "base/values.h" +#include "chrome/browser/sync/shared_value.h" + +namespace browser_sync { + +// A thread-safe wrapper around an immutable DictionaryValue. Used +// for passing around event details to different threads. +class JsEventDetails { + public: + // Uses an empty dictionary. + JsEventDetails(); + + // Takes over the data in |details|, leaving |details| empty. + explicit JsEventDetails(DictionaryValue* details); + + ~JsEventDetails(); + + const DictionaryValue& Get() const; + + std::string ToString() const; + + // Copy constructor and assignment operator welcome. + + private: + scoped_refptr<const SharedValue<DictionaryValue> > details_; +}; + +} // namespace browser_sync + +#endif // CHROME_BROWSER_SYNC_JS_EVENT_DETAILS_H_ diff --git a/chrome/browser/sync/js_event_details_unittest.cc b/chrome/browser/sync/js_event_details_unittest.cc new file mode 100644 index 0000000..60ac2e4 --- /dev/null +++ b/chrome/browser/sync/js_event_details_unittest.cc @@ -0,0 +1,36 @@ +// Copyright (c) 2011 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 "chrome/browser/sync/js_event_details.h" + +#include "base/memory/scoped_ptr.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace browser_sync { +namespace { + +class JsEventDetailsTest : public testing::Test {}; + +TEST_F(JsEventDetailsTest, EmptyList) { + JsEventDetails details; + EXPECT_TRUE(details.Get().empty()); + EXPECT_EQ("{}", details.ToString()); +} + +TEST_F(JsEventDetailsTest, FromDictionary) { + DictionaryValue dict; + dict.SetString("foo", "bar"); + dict.Set("baz", new ListValue()); + + scoped_ptr<DictionaryValue> dict_copy(dict.DeepCopy()); + + JsEventDetails details(&dict); + + // |details| should take over |dict|'s data. + EXPECT_TRUE(dict.empty()); + EXPECT_TRUE(details.Get().Equals(dict_copy.get())); +} + +} // namespace +} // namespace browser_sync diff --git a/chrome/browser/sync/js_event_handler.h b/chrome/browser/sync/js_event_handler.h index 058df9e..9a16e65 100644 --- a/chrome/browser/sync/js_event_handler.h +++ b/chrome/browser/sync/js_event_handler.h @@ -13,13 +13,14 @@ namespace browser_sync { class JsArgList; +class JsEventDetails; // An interface for objects that handle Javascript events (e.g., // WebUIs). class JsEventHandler { public: virtual void HandleJsEvent( - const std::string& name, const JsArgList& args) = 0; + const std::string& name, const JsEventDetails& details) = 0; virtual void HandleJsMessageReply( const std::string& name, const JsArgList& args) = 0; diff --git a/chrome/browser/sync/js_event_handler_list.cc b/chrome/browser/sync/js_event_handler_list.cc index 3629fb2..984f2a6 100644 --- a/chrome/browser/sync/js_event_handler_list.cc +++ b/chrome/browser/sync/js_event_handler_list.cc @@ -8,6 +8,7 @@ #include "base/logging.h" #include "chrome/browser/sync/js_backend.h" +#include "chrome/browser/sync/js_event_details.h" #include "chrome/browser/sync/js_event_handler.h" namespace browser_sync { @@ -76,8 +77,8 @@ void JsEventHandlerList::ProcessMessage( } void JsEventHandlerList::RouteJsEvent(const std::string& name, - const JsArgList& args) { - FOR_EACH_OBSERVER(JsEventHandler, handlers_, HandleJsEvent(name, args)); + const JsEventDetails& details) { + FOR_EACH_OBSERVER(JsEventHandler, handlers_, HandleJsEvent(name, details)); } void JsEventHandlerList::RouteJsMessageReply(const std::string& name, diff --git a/chrome/browser/sync/js_event_handler_list.h b/chrome/browser/sync/js_event_handler_list.h index a1f0946..1fd68c1 100644 --- a/chrome/browser/sync/js_event_handler_list.h +++ b/chrome/browser/sync/js_event_handler_list.h @@ -48,7 +48,7 @@ class JsEventHandlerList : public JsFrontend, public JsEventRouter { // JsEventRouter implementation. Routes the event to the // appropriate handler(s). virtual void RouteJsEvent(const std::string& name, - const JsArgList& args) OVERRIDE; + const JsEventDetails& details) OVERRIDE; virtual void RouteJsMessageReply(const std::string& name, const JsArgList& args, const JsEventHandler* target) OVERRIDE; diff --git a/chrome/browser/sync/js_event_handler_list_unittest.cc b/chrome/browser/sync/js_event_handler_list_unittest.cc index 52f0265..15687d8 100644 --- a/chrome/browser/sync/js_event_handler_list_unittest.cc +++ b/chrome/browser/sync/js_event_handler_list_unittest.cc @@ -6,6 +6,7 @@ #include "base/values.h" #include "chrome/browser/sync/js_arg_list.h" +#include "chrome/browser/sync/js_event_details.h" #include "chrome/browser/sync/js_test_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -13,11 +14,13 @@ namespace browser_sync { namespace { +using ::testing::InSequence; using ::testing::StrictMock; class JsEventHandlerListTest : public testing::Test {}; TEST_F(JsEventHandlerListTest, Basic) { + InSequence dummy; // |backend| must outlive |event_handlers|. StrictMock<MockJsBackend> backend; @@ -28,22 +31,31 @@ TEST_F(JsEventHandlerListTest, Basic) { arg_list2.Append(Value::CreateIntegerValue(5)); JsArgList args1(&arg_list1), args2(&arg_list2); + DictionaryValue details_dict1, details_dict2; + details_dict1.SetString("foo", "bar"); + details_dict2.SetInteger("baz", 5); + JsEventDetails details1(&details_dict1), details2(&details_dict2); + StrictMock<MockJsEventHandler> handler1, handler2; // Once from each call to AddHandler(). EXPECT_CALL(backend, SetParentJsEventRouter(&event_handlers)).Times(2); - // Once from the second RemoveHandler(), once from the destructor. - EXPECT_CALL(backend, RemoveParentJsEventRouter()).Times(2); + EXPECT_CALL(backend, ProcessMessage("test1", HasArgs(args2), &handler1)); - EXPECT_CALL(backend, ProcessMessage("test2", HasArgs(args1), &handler2)); + EXPECT_CALL(handler2, HandleJsMessageReply("reply2", HasArgs(args1))); EXPECT_CALL(handler1, HandleJsMessageReply("reply1", HasArgs(args2))); - EXPECT_CALL(handler1, HandleJsEvent("event", HasArgs(args1))); + EXPECT_CALL(handler1, HandleJsEvent("event", HasDetails(details1))); + EXPECT_CALL(handler2, HandleJsEvent("event", HasDetails(details1))); + + EXPECT_CALL(backend, ProcessMessage("test2", HasArgs(args1), &handler2)); - 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))); + EXPECT_CALL(handler2, HandleJsEvent("anotherevent", HasDetails(details2))); + + // Once from the second call to RemoveHandler(), once from the + // destructor. + EXPECT_CALL(backend, RemoveParentJsEventRouter()).Times(2); event_handlers.SetBackend(&backend); @@ -54,7 +66,7 @@ TEST_F(JsEventHandlerListTest, Basic) { event_handlers.RouteJsMessageReply("reply2", args1, &handler2); event_handlers.RouteJsMessageReply("reply1", args2, &handler1); - event_handlers.RouteJsEvent("event", args1); + event_handlers.RouteJsEvent("event", details1); event_handlers.RemoveHandler(&handler1); @@ -62,7 +74,7 @@ TEST_F(JsEventHandlerListTest, Basic) { event_handlers.RouteJsMessageReply("droppedreply1", args1, &handler1); event_handlers.RouteJsMessageReply("anotherreply2", args2, &handler2); - event_handlers.RouteJsEvent("anotherevent", args2); + event_handlers.RouteJsEvent("anotherevent", details2); event_handlers.RemoveHandler(&handler2); @@ -70,7 +82,7 @@ TEST_F(JsEventHandlerListTest, Basic) { args1, &handler1); event_handlers.RouteJsMessageReply("anotheranotherreply2", args2, &handler2); - event_handlers.RouteJsEvent("droppedevent", args2); + event_handlers.RouteJsEvent("droppedevent", details2); // 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 9fad052..89839ab 100644 --- a/chrome/browser/sync/js_event_router.h +++ b/chrome/browser/sync/js_event_router.h @@ -13,6 +13,7 @@ namespace browser_sync { class JsArgList; +class JsEventDetails; class JsEventHandler; // An interface for objects that don't directly handle Javascript @@ -21,7 +22,7 @@ class JsEventHandler; class JsEventRouter { public: virtual void RouteJsEvent( - const std::string& name, const JsArgList& args) = 0; + const std::string& name, const JsEventDetails& details) = 0; // |target| is const because it shouldn't be used except by the // router that directly knows about it (which can then safely cast diff --git a/chrome/browser/sync/js_sync_manager_observer.cc b/chrome/browser/sync/js_sync_manager_observer.cc index 39bf4eb..7faf4ec 100644 --- a/chrome/browser/sync/js_sync_manager_observer.cc +++ b/chrome/browser/sync/js_sync_manager_observer.cc @@ -9,6 +9,7 @@ #include "base/logging.h" #include "base/values.h" #include "chrome/browser/sync/js_arg_list.h" +#include "chrome/browser/sync/js_event_details.h" #include "chrome/browser/sync/js_event_router.h" #include "chrome/browser/sync/sessions/session_state.h" #include "chrome/browser/sync/syncable/model_type.h" @@ -27,94 +28,92 @@ void JsSyncManagerObserver::OnChangesApplied( const sync_api::BaseTransaction* trans, const sync_api::SyncManager::ChangeRecord* changes, int change_count) { - ListValue return_args; - return_args.Append(Value::CreateStringValue( - syncable::ModelTypeToString(model_type))); + DictionaryValue details; + details.SetString("modelType", syncable::ModelTypeToString(model_type)); ListValue* change_values = new ListValue(); - return_args.Append(change_values); + details.Set("changes", change_values); for (int i = 0; i < change_count; ++i) { change_values->Append(changes[i].ToValue(trans)); } - parent_router_->RouteJsEvent("onChangesApplied", JsArgList(&return_args)); + parent_router_->RouteJsEvent("onChangesApplied", JsEventDetails(&details)); } void JsSyncManagerObserver::OnChangesComplete( syncable::ModelType model_type) { - ListValue return_args; - return_args.Append(Value::CreateStringValue( - syncable::ModelTypeToString(model_type))); - parent_router_->RouteJsEvent("onChangesComplete", JsArgList(&return_args)); + DictionaryValue details; + details.SetString("modelType", syncable::ModelTypeToString(model_type)); + parent_router_->RouteJsEvent("onChangesComplete", JsEventDetails(&details)); } void JsSyncManagerObserver::OnSyncCycleCompleted( const sessions::SyncSessionSnapshot* snapshot) { - ListValue return_args; - return_args.Append(snapshot->ToValue()); + DictionaryValue details; + details.Set("snapshot", snapshot->ToValue()); parent_router_->RouteJsEvent("onSyncCycleCompleted", - JsArgList(&return_args)); + JsEventDetails(&details)); } void JsSyncManagerObserver::OnAuthError( const GoogleServiceAuthError& auth_error) { - ListValue return_args; - return_args.Append(auth_error.ToValue()); - parent_router_->RouteJsEvent("onAuthError", JsArgList(&return_args)); + DictionaryValue details; + details.Set("authError", auth_error.ToValue()); + parent_router_->RouteJsEvent("onAuthError", JsEventDetails(&details)); } void JsSyncManagerObserver::OnUpdatedToken(const std::string& token) { - ListValue return_args; - return_args.Append(Value::CreateStringValue("<redacted>")); - parent_router_->RouteJsEvent("onUpdatedToken", JsArgList(&return_args)); + DictionaryValue details; + details.SetString("token", "<redacted>"); + parent_router_->RouteJsEvent("onUpdatedToken", JsEventDetails(&details)); } void JsSyncManagerObserver::OnPassphraseRequired( sync_api::PassphraseRequiredReason reason) { - ListValue return_args; - - return_args.Append(Value::CreateStringValue( - sync_api::PassphraseRequiredReasonToString(reason))); + DictionaryValue details; + details.SetString("reason", + sync_api::PassphraseRequiredReasonToString(reason)); parent_router_->RouteJsEvent("onPassphraseRequired", - JsArgList(&return_args)); + JsEventDetails(&details)); } void JsSyncManagerObserver::OnPassphraseAccepted( const std::string& bootstrap_token) { - ListValue return_args; - return_args.Append(Value::CreateStringValue("<redacted>")); + DictionaryValue details; + details.SetString("bootstrapToken", "<redacted>"); parent_router_->RouteJsEvent("onPassphraseAccepted", - JsArgList(&return_args)); + JsEventDetails(&details)); } void JsSyncManagerObserver::OnEncryptionComplete( const syncable::ModelTypeSet& encrypted_types) { - ListValue return_args; - return_args.Append(syncable::ModelTypeSetToValue(encrypted_types)); + DictionaryValue details; + details.Set("encryptedTypes", + syncable::ModelTypeSetToValue(encrypted_types)); parent_router_->RouteJsEvent("onEncryptionComplete", - JsArgList(&return_args)); + JsEventDetails(&details)); } void JsSyncManagerObserver::OnMigrationNeededForTypes( const syncable::ModelTypeSet& types) { - ListValue return_args; - return_args.Append(syncable::ModelTypeSetToValue(types)); + DictionaryValue details; + details.Set("types", syncable::ModelTypeSetToValue(types)); parent_router_->RouteJsEvent("onMigrationNeededForTypes", - JsArgList(&return_args)); + JsEventDetails(&details)); } void JsSyncManagerObserver::OnInitializationComplete() { - parent_router_->RouteJsEvent("onInitializationComplete", JsArgList()); + parent_router_->RouteJsEvent("onInitializationComplete", JsEventDetails()); } void JsSyncManagerObserver::OnStopSyncingPermanently() { - parent_router_->RouteJsEvent("onStopSyncingPermanently", JsArgList()); + parent_router_->RouteJsEvent("onStopSyncingPermanently", JsEventDetails()); } void JsSyncManagerObserver::OnClearServerDataSucceeded() { - parent_router_->RouteJsEvent("onClearServerDataSucceeded", JsArgList()); + parent_router_->RouteJsEvent("onClearServerDataSucceeded", JsEventDetails()); } void JsSyncManagerObserver::OnClearServerDataFailed() { - parent_router_->RouteJsEvent("onClearServerDataFailed", JsArgList()); + parent_router_->RouteJsEvent("onClearServerDataFailed", JsEventDetails()); } } // 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 000c433..ee2d76f 100644 --- a/chrome/browser/sync/js_sync_manager_observer_unittest.cc +++ b/chrome/browser/sync/js_sync_manager_observer_unittest.cc @@ -10,6 +10,7 @@ #include "base/values.h" #include "chrome/browser/sync/engine/syncapi.h" #include "chrome/browser/sync/js_arg_list.h" +#include "chrome/browser/sync/js_event_details.h" #include "chrome/browser/sync/js_test_util.h" #include "chrome/browser/sync/sessions/session_state.h" #include "chrome/browser/sync/syncable/model_type.h" @@ -35,16 +36,16 @@ TEST_F(JsSyncManagerObserverTest, NoArgNotifiations) { EXPECT_CALL(mock_router_, RouteJsEvent("onInitializationComplete", - HasArgs(JsArgList()))); + HasDetails(JsEventDetails()))); EXPECT_CALL(mock_router_, RouteJsEvent("onStopSyncingPermanently", - HasArgs(JsArgList()))); + HasDetails(JsEventDetails()))); EXPECT_CALL(mock_router_, RouteJsEvent("onClearServerDataSucceeded", - HasArgs(JsArgList()))); + HasDetails(JsEventDetails()))); EXPECT_CALL(mock_router_, RouteJsEvent("onClearServerDataFailed", - HasArgs(JsArgList()))); + HasDetails(JsEventDetails()))); sync_manager_observer_.OnInitializationComplete(); sync_manager_observer_.OnStopSyncingPermanently(); @@ -57,13 +58,13 @@ TEST_F(JsSyncManagerObserverTest, OnChangesComplete) { for (int i = syncable::FIRST_REAL_MODEL_TYPE; i < syncable::MODEL_TYPE_COUNT; ++i) { - const std::string& model_type_str = - syncable::ModelTypeToString(syncable::ModelTypeFromInt(i)); - ListValue expected_args; - expected_args.Append(Value::CreateStringValue(model_type_str)); + DictionaryValue expected_details; + expected_details.SetString( + "modelType", + syncable::ModelTypeToString(syncable::ModelTypeFromInt(i))); EXPECT_CALL(mock_router_, RouteJsEvent("onChangesComplete", - HasArgsAsList(expected_args))); + HasDetailsAsDictionary(expected_details))); } for (int i = syncable::FIRST_REAL_MODEL_TYPE; @@ -87,24 +88,24 @@ TEST_F(JsSyncManagerObserverTest, OnSyncCycleCompleted) { 5, false, sessions::SyncSourceInfo()); - ListValue expected_args; - expected_args.Append(snapshot.ToValue()); + DictionaryValue expected_details; + expected_details.Set("snapshot", snapshot.ToValue()); EXPECT_CALL(mock_router_, RouteJsEvent("onSyncCycleCompleted", - HasArgsAsList(expected_args))); + HasDetailsAsDictionary(expected_details))); sync_manager_observer_.OnSyncCycleCompleted(&snapshot); } TEST_F(JsSyncManagerObserverTest, OnAuthError) { GoogleServiceAuthError error(GoogleServiceAuthError::TWO_FACTOR); - ListValue expected_args; - expected_args.Append(error.ToValue()); + DictionaryValue expected_details; + expected_details.Set("authError", error.ToValue()); EXPECT_CALL(mock_router_, RouteJsEvent("onAuthError", - HasArgsAsList(expected_args))); + HasDetailsAsDictionary(expected_details))); sync_manager_observer_.OnAuthError(error); } @@ -112,35 +113,40 @@ TEST_F(JsSyncManagerObserverTest, OnAuthError) { TEST_F(JsSyncManagerObserverTest, OnPassphraseRequired) { InSequence dummy; - ListValue reason_passphrase_not_required_args; - ListValue reason_encryption_args; - ListValue reason_decryption_args; - ListValue reason_set_passphrase_failed_args; + DictionaryValue reason_passphrase_not_required_details; + DictionaryValue reason_encryption_details; + DictionaryValue reason_decryption_details; + DictionaryValue reason_set_passphrase_failed_details; - reason_passphrase_not_required_args.Append(Value::CreateStringValue( + reason_passphrase_not_required_details.SetString( + "reason", sync_api::PassphraseRequiredReasonToString( - sync_api::REASON_PASSPHRASE_NOT_REQUIRED))); - reason_encryption_args.Append(Value::CreateStringValue( - sync_api::PassphraseRequiredReasonToString(sync_api::REASON_ENCRYPTION))); - reason_decryption_args.Append(Value::CreateStringValue( - sync_api::PassphraseRequiredReasonToString(sync_api::REASON_DECRYPTION))); - reason_set_passphrase_failed_args.Append(Value::CreateStringValue( + sync_api::REASON_PASSPHRASE_NOT_REQUIRED)); + reason_encryption_details.SetString( + "reason", + sync_api::PassphraseRequiredReasonToString(sync_api::REASON_ENCRYPTION)); + reason_decryption_details.SetString( + "reason", + sync_api::PassphraseRequiredReasonToString(sync_api::REASON_DECRYPTION)); + reason_set_passphrase_failed_details.SetString( + "reason", sync_api::PassphraseRequiredReasonToString( - sync_api::REASON_SET_PASSPHRASE_FAILED))); + sync_api::REASON_SET_PASSPHRASE_FAILED)); EXPECT_CALL(mock_router_, - RouteJsEvent( - "onPassphraseRequired", - HasArgsAsList(reason_passphrase_not_required_args))); + RouteJsEvent("onPassphraseRequired", + HasDetailsAsDictionary( + reason_passphrase_not_required_details))); EXPECT_CALL(mock_router_, RouteJsEvent("onPassphraseRequired", - HasArgsAsList(reason_encryption_args))); + HasDetailsAsDictionary(reason_encryption_details))); EXPECT_CALL(mock_router_, RouteJsEvent("onPassphraseRequired", - HasArgsAsList(reason_decryption_args))); + HasDetailsAsDictionary(reason_decryption_details))); EXPECT_CALL(mock_router_, RouteJsEvent("onPassphraseRequired", - HasArgsAsList(reason_set_passphrase_failed_args))); + HasDetailsAsDictionary( + reason_set_passphrase_failed_details))); sync_manager_observer_.OnPassphraseRequired( sync_api::REASON_PASSPHRASE_NOT_REQUIRED); @@ -151,26 +157,29 @@ TEST_F(JsSyncManagerObserverTest, OnPassphraseRequired) { } TEST_F(JsSyncManagerObserverTest, SensitiveNotifiations) { - ListValue redacted_args; - redacted_args.Append(Value::CreateStringValue("<redacted>")); + DictionaryValue redacted_token_details; + redacted_token_details.SetString("token", "<redacted>"); + DictionaryValue redacted_bootstrap_token_details; + redacted_bootstrap_token_details.SetString("bootstrapToken", "<redacted>"); EXPECT_CALL(mock_router_, RouteJsEvent("onUpdatedToken", - HasArgsAsList(redacted_args))); + HasDetailsAsDictionary(redacted_token_details))); EXPECT_CALL(mock_router_, - RouteJsEvent("onPassphraseAccepted", - HasArgsAsList(redacted_args))); + RouteJsEvent( + "onPassphraseAccepted", + HasDetailsAsDictionary(redacted_bootstrap_token_details))); sync_manager_observer_.OnUpdatedToken("sensitive_token"); sync_manager_observer_.OnPassphraseAccepted("sensitive_token"); } TEST_F(JsSyncManagerObserverTest, OnEncryptionComplete) { - ListValue expected_args; + DictionaryValue expected_details; ListValue* encrypted_type_values = new ListValue(); + expected_details.Set("encryptedTypes", encrypted_type_values); syncable::ModelTypeSet encrypted_types; - expected_args.Append(encrypted_type_values); for (int i = syncable::FIRST_REAL_MODEL_TYPE; i < syncable::MODEL_TYPE_COUNT; ++i) { syncable::ModelType type = syncable::ModelTypeFromInt(i); @@ -181,17 +190,17 @@ TEST_F(JsSyncManagerObserverTest, OnEncryptionComplete) { EXPECT_CALL(mock_router_, RouteJsEvent("onEncryptionComplete", - HasArgsAsList(expected_args))); + HasDetailsAsDictionary(expected_details))); sync_manager_observer_.OnEncryptionComplete(encrypted_types); } TEST_F(JsSyncManagerObserverTest, OnMigrationNeededForTypes) { - ListValue expected_args; + DictionaryValue expected_details; ListValue* type_values = new ListValue(); + expected_details.Set("types", type_values); syncable::ModelTypeSet types; - expected_args.Append(type_values); for (int i = syncable::FIRST_REAL_MODEL_TYPE; i < syncable::MODEL_TYPE_COUNT; ++i) { syncable::ModelType type = syncable::ModelTypeFromInt(i); @@ -202,7 +211,7 @@ TEST_F(JsSyncManagerObserverTest, OnMigrationNeededForTypes) { EXPECT_CALL(mock_router_, RouteJsEvent("onMigrationNeededForTypes", - HasArgsAsList(expected_args))); + HasDetailsAsDictionary(expected_details))); sync_manager_observer_.OnMigrationNeededForTypes(types); } @@ -270,17 +279,17 @@ TEST_F(JsSyncManagerObserverTest, OnChangesApplied) { i < syncable::MODEL_TYPE_COUNT; ++i) { const std::string& model_type_str = syncable::ModelTypeToString(syncable::ModelTypeFromInt(i)); - ListValue expected_args; - expected_args.Append(Value::CreateStringValue(model_type_str)); + DictionaryValue expected_details; + expected_details.SetString("modelType", model_type_str); ListValue* expected_changes = new ListValue(); - expected_args.Append(expected_changes); + expected_details.Set("changes", expected_changes); for (int j = i; j < syncable::MODEL_TYPE_COUNT; ++j) { sync_api::ReadTransaction trans(test_user_share.user_share()); expected_changes->Append(changes[j].ToValue(&trans)); } EXPECT_CALL(mock_router_, RouteJsEvent("onChangesApplied", - HasArgsAsList(expected_args))); + HasDetailsAsDictionary(expected_details))); } // Fire OnChangesApplied() for each data type. diff --git a/chrome/browser/sync/js_test_util.cc b/chrome/browser/sync/js_test_util.cc index 1d8d329..7884ea2 100644 --- a/chrome/browser/sync/js_test_util.cc +++ b/chrome/browser/sync/js_test_util.cc @@ -7,6 +7,7 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "chrome/browser/sync/js_arg_list.h" +#include "chrome/browser/sync/js_event_details.h" namespace browser_sync { @@ -14,6 +15,10 @@ void PrintTo(const JsArgList& args, ::std::ostream* os) { *os << args.ToString(); } +void PrintTo(const JsEventDetails& details, ::std::ostream* os) { + *os << details.ToString(); +} + namespace { // Matcher implementation for HasArgs(). @@ -46,6 +51,36 @@ class HasArgsMatcher DISALLOW_COPY_AND_ASSIGN(HasArgsMatcher); }; +// Matcher implementation for HasDetails(). +class HasDetailsMatcher + : public ::testing::MatcherInterface<const JsEventDetails&> { + public: + explicit HasDetailsMatcher(const JsEventDetails& expected_details) + : expected_details_(expected_details) {} + + virtual ~HasDetailsMatcher() {} + + virtual bool MatchAndExplain( + const JsEventDetails& details, + ::testing::MatchResultListener* listener) const { + // No need to annotate listener since we already define PrintTo(). + return details.Get().Equals(&expected_details_.Get()); + } + + virtual void DescribeTo(::std::ostream* os) const { + *os << "has details " << expected_details_.ToString(); + } + + virtual void DescribeNegationTo(::std::ostream* os) const { + *os << "doesn't have details " << expected_details_.ToString(); + } + + private: + const JsEventDetails expected_details_; + + DISALLOW_COPY_AND_ASSIGN(HasDetailsMatcher); +}; + } // namespace ::testing::Matcher<const JsArgList&> HasArgs(const JsArgList& expected_args) { @@ -58,6 +93,18 @@ class HasArgsMatcher return HasArgs(JsArgList(expected_args_copy.get())); } +::testing::Matcher<const JsEventDetails&> HasDetails( + const JsEventDetails& expected_details) { + return ::testing::MakeMatcher(new HasDetailsMatcher(expected_details)); +} + +::testing::Matcher<const JsEventDetails&> HasDetailsAsDictionary( + const DictionaryValue& expected_details) { + scoped_ptr<DictionaryValue> expected_details_copy( + expected_details.DeepCopy()); + return HasDetails(JsEventDetails(expected_details_copy.get())); +} + MockJsBackend::MockJsBackend() {} MockJsBackend::~MockJsBackend() {} diff --git a/chrome/browser/sync/js_test_util.h b/chrome/browser/sync/js_test_util.h index 85b4fc7..2571e8b 100644 --- a/chrome/browser/sync/js_test_util.h +++ b/chrome/browser/sync/js_test_util.h @@ -15,24 +15,37 @@ #include "chrome/browser/sync/js_event_router.h" #include "testing/gmock/include/gmock/gmock.h" +class DictionaryValue; class ListValue; namespace browser_sync { class JsArgList; +class JsEventDetails; // Defined for googletest. Equivalent to "*os << args.ToString()". void PrintTo(const JsArgList& args, ::std::ostream* os); +void PrintTo(const JsEventDetails& details, ::std::ostream* os); -// A matcher for gmock. Use like: +// A gmock matcher for JsArgList. Use like: // -// EXPECT_CALL(mock, ProcessMessage("foo", HasArgs(args))).Times(1); +// EXPECT_CALL(mock, HandleJsMessageReply("foo", HasArgs(expected_args))); ::testing::Matcher<const JsArgList&> HasArgs(const JsArgList& expected_args); // Like HasArgs() but takes a ListValue instead. ::testing::Matcher<const JsArgList&> HasArgsAsList( const ListValue& expected_args); +// A gmock matcher for JsEventDetails. Use like: +// +// EXPECT_CALL(mock, HandleJsEvent("foo", HasArgs(expected_details))); +::testing::Matcher<const JsEventDetails&> HasDetails( + const JsEventDetails& expected_details); + +// Like HasDetails() but takes a DictionaryValue instead. +::testing::Matcher<const JsEventDetails&> HasDetailsAsDictionary( + const DictionaryValue& expected_details); + // Mocks. class MockJsBackend : public JsBackend { @@ -64,7 +77,8 @@ class MockJsEventHandler : public JsEventHandler { MockJsEventHandler(); ~MockJsEventHandler(); - MOCK_METHOD2(HandleJsEvent, void(const ::std::string&, const JsArgList&)); + MOCK_METHOD2(HandleJsEvent, + void(const ::std::string&, const JsEventDetails&)); MOCK_METHOD2(HandleJsMessageReply, void(const ::std::string&, const JsArgList&)); }; @@ -75,7 +89,7 @@ class MockJsEventRouter : public JsEventRouter { ~MockJsEventRouter(); MOCK_METHOD2(RouteJsEvent, - void(const ::std::string&, const JsArgList&)); + void(const ::std::string&, const JsEventDetails&)); 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 0e3fe71..9993bfa 100644 --- a/chrome/browser/sync/profile_sync_service.cc +++ b/chrome/browser/sync/profile_sync_service.cc @@ -33,6 +33,7 @@ #include "chrome/browser/sync/glue/data_type_manager.h" #include "chrome/browser/sync/glue/session_data_type_controller.h" #include "chrome/browser/sync/js_arg_list.h" +#include "chrome/browser/sync/js_event_details.h" #include "chrome/browser/sync/profile_sync_factory.h" #include "chrome/browser/sync/signin_manager.h" #include "chrome/browser/ui/browser.h" @@ -453,7 +454,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()); + "onServiceStateChanged", browser_sync::JsEventDetails()); } // static diff --git a/chrome/browser/sync/profile_sync_service_unittest.cc b/chrome/browser/sync/profile_sync_service_unittest.cc index 80ac89a..c7a335b 100644 --- a/chrome/browser/sync/profile_sync_service_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_unittest.cc @@ -10,6 +10,7 @@ #include "chrome/browser/sync/glue/bookmark_data_type_controller.h" #include "chrome/browser/sync/glue/data_type_controller.h" #include "chrome/browser/sync/js_arg_list.h" +#include "chrome/browser/sync/js_event_details.h" #include "chrome/browser/sync/js_test_util.h" #include "chrome/browser/sync/profile_sync_factory_mock.h" #include "chrome/browser/sync/test_profile_sync_service.h" @@ -171,8 +172,8 @@ TEST_F(ProfileSyncServiceTest, StrictMock<MockJsEventHandler> event_handler; EXPECT_CALL(event_handler, - HandleJsEvent("onSyncServiceStateChanged", - HasArgs(JsArgList()))).Times(AtLeast(3)); + HandleJsEvent("onServiceStateChanged", + HasDetails(JsEventDetails()))).Times(AtLeast(3)); // For some reason, these events may or may not fire. // // TODO(akalin): Figure out exactly why there's non-determinism @@ -181,7 +182,7 @@ TEST_F(ProfileSyncServiceTest, .Times(AtMost(1)); EXPECT_CALL(event_handler, HandleJsEvent("onChangesComplete", _)) .Times(AtMost(1)); - EXPECT_CALL(event_handler, HandleJsEvent("onSyncNotificationStateChange", _)) + EXPECT_CALL(event_handler, HandleJsEvent("onNotificationStateChange", _)) .Times(AtMost(1)); EXPECT_EQ(NULL, service_->GetBackendForTest()); @@ -215,7 +216,7 @@ TEST_F(ProfileSyncServiceTest, JsFrontendProcessMessageBasic) { .Times(AtMost(1)); EXPECT_CALL(event_handler, HandleJsEvent("onChangesComplete", _)) .Times(AtMost(1)); - EXPECT_CALL(event_handler, HandleJsEvent("onSyncNotificationStateChange", _)) + EXPECT_CALL(event_handler, HandleJsEvent("onNotificationStateChange", _)) .Times(AtMost(1)); ListValue arg_list1; @@ -274,7 +275,7 @@ TEST_F(ProfileSyncServiceTest, .Times(AtMost(1)); EXPECT_CALL(event_handler, HandleJsEvent("onChangesComplete", _)) .Times(AtMost(1)); - EXPECT_CALL(event_handler, HandleJsEvent("onSyncNotificationStateChange", _)) + EXPECT_CALL(event_handler, HandleJsEvent("onNotificationStateChange", _)) .Times(AtMost(1)); ListValue arg_list1; @@ -298,10 +299,10 @@ TEST_F(ProfileSyncServiceTest, EXPECT_CALL(event_handler, HandleJsMessageReply("delayTestMessage3", HasArgs(args3))); - const JsArgList kNoArgs; + const JsEventDetails kNoDetails; - EXPECT_CALL(event_handler, HandleJsEvent("onSyncServiceStateChanged", - HasArgs(kNoArgs))).Times(AtLeast(3)); + EXPECT_CALL(event_handler, HandleJsEvent("onServiceStateChanged", + HasDetails(kNoDetails))).Times(AtLeast(3)); JsFrontend* js_backend = service_->GetJsFrontend(); @@ -321,6 +322,8 @@ TEST_F(ProfileSyncServiceTest, // Fires delayTestMessage3. ui_loop_.RunAllPending(); + const JsArgList kNoArgs; + js_backend->ProcessMessage("delayNotRepliedTo", kNoArgs, &event_handler); js_backend->RemoveHandler(&event_handler); diff --git a/chrome/browser/sync/shared_value.h b/chrome/browser/sync/shared_value.h new file mode 100644 index 0000000..50eef2e --- /dev/null +++ b/chrome/browser/sync/shared_value.h @@ -0,0 +1,52 @@ +// Copyright (c) 2011 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. + +#ifndef CHROME_BROWSER_SYNC_SHARED_VALUE_H_ +#define CHROME_BROWSER_SYNC_SHARED_VALUE_H_ +#pragma once + +#include "base/memory/ref_counted.h" + +namespace browser_sync { + +// Forward declaration for SharedValueTraits. +template <class ValueType> +class SharedValue; + +// VS2005 workaround taken from base/observer_list_threadsafe.h. +template <class ValueType> +struct SharedValueTraits { + static void Destruct(const SharedValue<ValueType>* x) { + delete x; + } +}; + +// A ref-counted thread-safe wrapper around an immutable value. +// +// ValueType should be a subclass of Value that has a Swap() method. +template <class ValueType> +class SharedValue + : public base::RefCountedThreadSafe< + SharedValue<ValueType>, SharedValueTraits<ValueType> > { + public: + SharedValue() {} + // Takes over the data in |value|, leaving |value| empty. + explicit SharedValue(ValueType* value) { + value_.Swap(value); + } + + const ValueType& Get() const { + return value_; + } + + private: + ~SharedValue() {} + friend struct SharedValueTraits<ValueType>; + + ValueType value_; +}; + +} // namespace browser_sync + +#endif // CHROME_BROWSER_SYNC_SHARED_VALUE_H_ diff --git a/chrome/browser/ui/webui/sync_internals_ui.cc b/chrome/browser/ui/webui/sync_internals_ui.cc index 10102be..c719895 100644 --- a/chrome/browser/ui/webui/sync_internals_ui.cc +++ b/chrome/browser/ui/webui/sync_internals_ui.cc @@ -13,6 +13,7 @@ #include "base/values.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/js_arg_list.h" +#include "chrome/browser/sync/js_event_details.h" #include "chrome/browser/sync/js_frontend.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/sync_ui_util.h" @@ -52,12 +53,12 @@ void SyncInternalsUI::OnWebUISend(const GURL& source_url, // We handle this case directly because it needs to work even if // the sync service doesn't exist. if (name == "getAboutInfo") { - ListValue args; + ListValue return_args; DictionaryValue* about_info = new DictionaryValue(); - args.Append(about_info); + return_args.Append(about_info); ProfileSyncService* service = GetProfile()->GetProfileSyncService(); sync_ui_util::ConstructAboutInformation(service, about_info); - HandleJsMessageReply(name, browser_sync::JsArgList(&args)); + HandleJsMessageReply(name, browser_sync::JsArgList(&return_args)); } else { browser_sync::JsFrontend* backend = GetJsFrontend(); if (backend) { @@ -69,11 +70,13 @@ 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(); +void SyncInternalsUI::HandleJsEvent( + const std::string& name, + const browser_sync::JsEventDetails& details) { + VLOG(1) << "Handling event: " << name << " with details " + << details.ToString(); const std::string& event_handler = "chrome.sync." + name + ".fire"; - std::vector<const Value*> arg_list(args.Get().begin(), args.Get().end()); + std::vector<const Value*> arg_list(1, &details.Get()); CallJavascriptFunction(event_handler, arg_list); } diff --git a/chrome/browser/ui/webui/sync_internals_ui.h b/chrome/browser/ui/webui/sync_internals_ui.h index 6512fca..3339843 100644 --- a/chrome/browser/ui/webui/sync_internals_ui.h +++ b/chrome/browser/ui/webui/sync_internals_ui.h @@ -41,8 +41,9 @@ class SyncInternalsUI : public WebUI, public browser_sync::JsEventHandler { const ListValue& args) OVERRIDE; // browser_sync::JsEventHandler implementation. - virtual void HandleJsEvent(const std::string& name, - const browser_sync::JsArgList& args) OVERRIDE; + virtual void HandleJsEvent( + const std::string& name, + const browser_sync::JsEventDetails& details) OVERRIDE; virtual void HandleJsMessageReply( const std::string& name, const browser_sync::JsArgList& args) OVERRIDE; diff --git a/chrome/browser/ui/webui/sync_internals_ui_unittest.cc b/chrome/browser/ui/webui/sync_internals_ui_unittest.cc index dab0b3e..d581b73 100644 --- a/chrome/browser/ui/webui/sync_internals_ui_unittest.cc +++ b/chrome/browser/ui/webui/sync_internals_ui_unittest.cc @@ -10,6 +10,7 @@ #include "base/message_loop.h" #include "base/values.h" #include "chrome/browser/sync/js_arg_list.h" +#include "chrome/browser/sync/js_event_details.h" #include "chrome/browser/sync/js_test_util.h" #include "chrome/browser/sync/profile_sync_service_mock.h" #include "chrome/test/profile_mock.h" @@ -23,6 +24,7 @@ namespace { using browser_sync::HasArgsAsList; using browser_sync::JsArgList; +using browser_sync::JsEventDetails; using testing::NiceMock; using testing::Return; using testing::StrictMock; @@ -139,12 +141,9 @@ TEST_F(SyncInternalsUITest, HandleJsEvent) { EXPECT_CALL(*GetTestSyncInternalsUI(), ExecuteJavascript( - ASCIIToUTF16("chrome.sync.testMessage.fire(5,true);"))); + ASCIIToUTF16("chrome.sync.testMessage.fire({});"))); - ListValue args; - args.Append(Value::CreateIntegerValue(5)); - args.Append(Value::CreateBooleanValue(true)); - GetTestSyncInternalsUI()->HandleJsEvent("testMessage", JsArgList(&args)); + GetTestSyncInternalsUI()->HandleJsEvent("testMessage", JsEventDetails()); } TEST_F(SyncInternalsUITest, HandleJsEventNullService) { @@ -154,12 +153,9 @@ TEST_F(SyncInternalsUITest, HandleJsEventNullService) { EXPECT_CALL(*GetTestSyncInternalsUI(), ExecuteJavascript( - ASCIIToUTF16("chrome.sync.testMessage.fire(5,true);"))); + ASCIIToUTF16("chrome.sync.testMessage.fire({});"))); - ListValue args; - args.Append(Value::CreateIntegerValue(5)); - args.Append(Value::CreateBooleanValue(true)); - GetTestSyncInternalsUI()->HandleJsEvent("testMessage", JsArgList(&args)); + GetTestSyncInternalsUI()->HandleJsEvent("testMessage", JsEventDetails()); } TEST_F(SyncInternalsUITest, HandleJsMessageReply) { diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index b15b366..34ec4b0 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -607,6 +607,8 @@ 'browser/sync/js_arg_list.cc', 'browser/sync/js_arg_list.h', 'browser/sync/js_backend.h', + 'browser/sync/js_event_details.cc', + 'browser/sync/js_event_details.h', 'browser/sync/js_event_handler.h', 'browser/sync/js_event_handler_list.cc', 'browser/sync/js_event_handler_list.h', @@ -629,6 +631,7 @@ 'browser/sync/sessions/sync_session.h', 'browser/sync/sessions/sync_session_context.cc', 'browser/sync/sessions/sync_session_context.h', + 'browser/sync/shared_value.h', 'browser/sync/syncable/autofill_migration.h', 'browser/sync/syncable/blob.h', 'browser/sync/syncable/dir_open_result.h', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 978b042..9936850 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -2956,6 +2956,7 @@ 'browser/sync/engine/syncapi_mock.h', 'browser/sync/engine/verify_updates_command_unittest.cc', 'browser/sync/js_arg_list_unittest.cc', + 'browser/sync/js_event_details_unittest.cc', 'browser/sync/js_event_handler_list_unittest.cc', 'browser/sync/js_sync_manager_observer_unittest.cc', 'browser/sync/notifier/cache_invalidation_packet_handler_unittest.cc', |