summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-10 09:23:39 +0000
committerakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-10 09:23:39 +0000
commitec5263a0914ca9f58586f3808b1ab45acd3b9400 (patch)
tree9e119d6b7578eb6ab348fd4334c5bd9c818f0bbe
parent46be25eca97a31cae1b48a59513591f32d0ce6b4 (diff)
downloadchromium_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
-rw-r--r--base/values.h5
-rw-r--r--chrome/browser/resources/sync_internals/about.html2
-rw-r--r--chrome/browser/resources/sync_internals/chrome_sync.js66
-rw-r--r--chrome/browser/resources/sync_internals/notifications.html21
-rw-r--r--chrome/browser/resources/sync_internals/sync_log.js115
-rw-r--r--chrome/browser/sync/engine/syncapi.cc18
-rw-r--r--chrome/browser/sync/engine/syncapi.h6
-rw-r--r--chrome/browser/sync/engine/syncapi_unittest.cc27
-rw-r--r--chrome/browser/sync/glue/sync_backend_host.cc9
-rw-r--r--chrome/browser/sync/glue/sync_backend_host.h4
-rw-r--r--chrome/browser/sync/js_arg_list.cc16
-rw-r--r--chrome/browser/sync/js_arg_list.h18
-rw-r--r--chrome/browser/sync/js_arg_list_unittest.cc1
-rw-r--r--chrome/browser/sync/js_event_details.cc29
-rw-r--r--chrome/browser/sync/js_event_details.h43
-rw-r--r--chrome/browser/sync/js_event_details_unittest.cc36
-rw-r--r--chrome/browser/sync/js_event_handler.h3
-rw-r--r--chrome/browser/sync/js_event_handler_list.cc5
-rw-r--r--chrome/browser/sync/js_event_handler_list.h2
-rw-r--r--chrome/browser/sync/js_event_handler_list_unittest.cc32
-rw-r--r--chrome/browser/sync/js_event_router.h3
-rw-r--r--chrome/browser/sync/js_sync_manager_observer.cc71
-rw-r--r--chrome/browser/sync/js_sync_manager_observer_unittest.cc105
-rw-r--r--chrome/browser/sync/js_test_util.cc47
-rw-r--r--chrome/browser/sync/js_test_util.h22
-rw-r--r--chrome/browser/sync/profile_sync_service.cc3
-rw-r--r--chrome/browser/sync/profile_sync_service_unittest.cc19
-rw-r--r--chrome/browser/sync/shared_value.h52
-rw-r--r--chrome/browser/ui/webui/sync_internals_ui.cc17
-rw-r--r--chrome/browser/ui/webui/sync_internals_ui.h5
-rw-r--r--chrome/browser/ui/webui/sync_internals_ui_unittest.cc16
-rw-r--r--chrome/chrome.gyp3
-rw-r--r--chrome/chrome_tests.gypi1
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',