diff options
author | rlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-07 20:30:34 +0000 |
---|---|---|
committer | rlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-07 20:30:34 +0000 |
commit | c77435705b8f6a9173cdecc5e6eeb2f1911cc48a (patch) | |
tree | 8d1113110fed798c28e18124c68440baeaeed88d | |
parent | e5af9bcbb29f9207de974e278e614ebc0609ea08 (diff) | |
download | chromium_src-c77435705b8f6a9173cdecc5e6eeb2f1911cc48a.zip chromium_src-c77435705b8f6a9173cdecc5e6eeb2f1911cc48a.tar.gz chromium_src-c77435705b8f6a9173cdecc5e6eeb2f1911cc48a.tar.bz2 |
sync: Re-implement getAllNodes WebUI function
Removes the existing implementation of getAllNodes. This was the last
function based on the old "makeSyncFunction" and "JsMessageHandler"
interface, so its removal leaves behind quite a bit of dead code. This
CL removes some of it. The rest will be removed in a future CL.
Replaces it with some infrastructure intended to be more compatible with
the future of sync, where each type is more independent. Requests to
getAllNodes are routed through a DirectoryTypeDebugInfoEmitter in the
ModelTypeRegistry. A NonBlockingTypeDebugInfoEmitter will be
implemented in a future CL.
The new system also intended to support "streaming" results. Rather
than waiting for all types to return their nodes, the system could be
modified to allow some types to get back to the JavaScript layer sooner
than others so it can display results earlier. However, we do not
currently take advantage of this functionality.
The return type of getAllNodes is now an array of per-type objects,
rather than one big list of nodes. This, too, should help us implement
streaming support in the future. For now, most of the JavaScript
callbacks will convert the data back to the old format before operating
on it.
BUG=328606
Review URL: https://codereview.chromium.org/224563004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@262193 0039d316-1c4b-4281-b951-d872f2087c98
29 files changed, 528 insertions, 311 deletions
diff --git a/chrome/browser/resources/sync_internals/chrome_sync.js b/chrome/browser/resources/sync_internals/chrome_sync.js index f8d9a2f..5bd7e6f 100644 --- a/chrome/browser/resources/sync_internals/chrome_sync.js +++ b/chrome/browser/resources/sync_internals/chrome_sync.js @@ -9,40 +9,6 @@ cr.define('chrome.sync', function() { 'use strict'; - function makeSyncFunction(name) { - var callbacks = []; - - // Calls the function, assuming the last argument is a callback to be - // called with the return value. - var fn = function() { - var args = Array.prototype.slice.call(arguments); - callbacks.push(args.pop()); - chrome.send(name, args); - }; - - // Handle a reply, assuming that messages are processed in FIFO order. - // Called by SyncInternalsUI::HandleJsReply(). - fn.handleReply = function() { - var args = Array.prototype.slice.call(arguments); - // Remove the callback before we call it since the callback may - // throw. - var callback = callbacks.shift(); - callback.apply(null, args); - }; - - return fn; - } - - var syncFunctions = [ - // Get an array containing a JSON representations of all known sync nodes. - 'getAllNodes', - ]; - - for (var i = 0; i < syncFunctions.length; ++i) { - var syncFunction = syncFunctions[i]; - chrome.sync[syncFunction] = makeSyncFunction(syncFunction); - } - /** * A simple timer to measure elapsed time. * @constructor @@ -103,11 +69,47 @@ cr.define('chrome.sync', function() { chrome.send('requestListOfTypes'); }; + /** + * Counter to uniquely identify requests while they're in progress. + * Used in the implementation of GetAllNodes. + */ + var requestId = 0; + + /** + * A map from counter values to asynchronous request callbacks. + * Used in the implementation of GetAllNodes. + * @type {{number: !Function}} + */ + var requestCallbacks = {}; + + /** + * Asks the browser to send us a copy of all existing sync nodes. + * Will eventually invoke the given callback with the results. + * + * @param {function(!Object)} callback The function to call with the response. + */ + var getAllNodes = function(callback) { + requestId++; + requestCallbacks[requestId] = callback; + chrome.send('getAllNodes', [requestId]); + }; + + /** + * Called from C++ with the response to a getAllNodes request. + * @param {number} id The requestId passed in with the request. + * @param {Object} response The response to the request. + */ + var getAllNodesCallback = function(id, response) { + requestCallbacks[id](response); + requestCallbacks[id] = undefined; + }; + return { makeTimer: makeTimer, dispatchEvent: dispatchEvent, events: new cr.EventTarget(), - + getAllNodes: getAllNodes, + getAllNodesCallback: getAllNodesCallback, registerForEvents: registerForEvents, requestUpdatedAboutInfo: requestUpdatedAboutInfo, requestListOfTypes: requestListOfTypes, diff --git a/chrome/browser/resources/sync_internals/data.js b/chrome/browser/resources/sync_internals/data.js index c0ef90e..6de42c7 100644 --- a/chrome/browser/resources/sync_internals/data.js +++ b/chrome/browser/resources/sync_internals/data.js @@ -57,7 +57,11 @@ function versionToDateString(version) { return date.toString(); } -function getFields(node) { +/** + * @param {!Object} node A JavaScript represenation of a sync entity. + * @return {string} A string representation of the sync entity. + */ +function serializeNode(node) { return allFields.map(function(field) { var fieldVal; if (field == 'SERVER_VERSION_TIME') { @@ -79,8 +83,11 @@ function getFields(node) { }); } -function isSelectedDatatype(node) { - var type = node.serverModelType; +/** + * @param {string} type The name of a sync model type. + * @return {boolean} True if the type's checkbox is selected. + */ +function isSelectedDatatype(type) { var typeCheckbox = $(type); // Some types, such as 'Top level folder', appear in the list of nodes // but not in the list of selectable items. @@ -116,7 +123,13 @@ function makeDateUserAgentHeader() { return dateUaHeader; } -function triggerDataDownload(data) { +/** + * Builds a summary of current state and exports it as a downloaded file. + * + * @param {!Array.<{type: string, nodes: !Array<!Object>}>} nodesMap + * Summary of local state by model type. + */ +function triggerDataDownload(nodesMap) { // Prepend a header with ISO date and useragent. var output = [makeDateUserAgentHeader()]; output.push('====='); @@ -124,16 +137,17 @@ function triggerDataDownload(data) { var aboutInfo = JSON.stringify(chrome.sync.aboutInfo, null, 2); output.push(aboutInfo); - if (data != null && data.length > 0) { + // Filter out non-selected types. + var selectedTypesNodes = nodesMap.filter(function(x) { + return isSelectedDatatype(x.type); + }); + + // Serialize the remaining nodes and add them to the output. + selectedTypesNodes.forEach(function(typeNodes) { output.push('====='); - var fieldLabels = allFields.join(','); - output.push(fieldLabels); + output.push(typeNodes.nodes.map(serializeNode).join('\n')); + }); - var data = data.filter(isSelectedDatatype); - data = data.map(getFields); - var dataAsString = data.join('\n'); - output.push(dataAsString); - } output = output.join('\n'); var anchor = $('dump-to-file-anchor'); diff --git a/chrome/browser/resources/sync_internals/sync_node_browser.js b/chrome/browser/resources/sync_internals/sync_node_browser.js index d20b864..3699164 100644 --- a/chrome/browser/resources/sync_internals/sync_node_browser.js +++ b/chrome/browser/resources/sync_internals/sync_node_browser.js @@ -178,7 +178,12 @@ clear(); setLastRefreshTime('In progress since ' + (new Date()).toLocaleString()); - chrome.sync.getAllNodes(function(nodes) { + chrome.sync.getAllNodes(function(nodeMap) { + // Put all nodes into one big list that ignores the type. + var nodes = nodeMap. + map(function(x) { return x.nodes; }). + reduce(function(a, b) { return a.concat(b); }); + var treeContainer = $('sync-node-tree-container'); var tree = document.createElement('tree'); tree.setAttribute('id', 'sync-node-tree'); diff --git a/chrome/browser/resources/sync_internals/sync_search.js b/chrome/browser/resources/sync_internals/sync_search.js index 7e3f345..9f491ec 100644 --- a/chrome/browser/resources/sync_internals/sync_search.js +++ b/chrome/browser/resources/sync_internals/sync_search.js @@ -47,11 +47,16 @@ cr.define('chrome.sync', function() { var searchId = ++currSearchId; try { var regex = new RegExp(query); - chrome.sync.getAllNodes(query, function(allNodes) { + chrome.sync.getAllNodes(function(node_map) { + // Put all nodes into one big list that ignores the type. + var nodes = node_map. + map(function(x) { return x.nodes; }). + reduce(function(a, b) { return a.concat(b); }); + if (currSearchId != searchId) { return; } - callback(allNodes.filter(function(elem) { + callback(nodes.filter(function(elem) { return regex.test(JSON.stringify(elem, null, 2)); }), null); }); diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h index 5b8afdc..3f7ea4d 100644 --- a/chrome/browser/sync/glue/sync_backend_host.h +++ b/chrome/browser/sync/glue/sync_backend_host.h @@ -206,6 +206,13 @@ class SyncBackendHost : public BackendDataTypeConfigurer { // Disables protocol event forwarding. virtual void DisableProtocolEventForwarding() = 0; + // Returns a ListValue representing all nodes for the specified types through + // |callback| on this thread. + virtual void GetAllNodesForTypes( + syncer::ModelTypeSet types, + base::Callback<void(const std::vector<syncer::ModelType>&, + ScopedVector<base::ListValue>)> type) = 0; + virtual base::MessageLoop* GetSyncLoopForTesting() = 0; DISALLOW_COPY_AND_ASSIGN(SyncBackendHost); diff --git a/chrome/browser/sync/glue/sync_backend_host_core.cc b/chrome/browser/sync/glue/sync_backend_host_core.cc index 9d54617..54c1c51 100644 --- a/chrome/browser/sync/glue/sync_backend_host_core.cc +++ b/chrome/browser/sync/glue/sync_backend_host_core.cc @@ -650,6 +650,33 @@ void SyncBackendHostCore::DeleteSyncDataFolder() { } } +void SyncBackendHostCore::GetAllNodesForTypes( + syncer::ModelTypeSet types, + scoped_refptr<base::SequencedTaskRunner> task_runner, + base::Callback<void(const std::vector<syncer::ModelType>& type, + ScopedVector<base::ListValue>)> callback) { + std::vector<syncer::ModelType> types_vector; + ScopedVector<base::ListValue> node_lists; + + syncer::ModelSafeRoutingInfo routes; + registrar_->GetModelSafeRoutingInfo(&routes); + syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routes); + + for (syncer::ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) { + types_vector.push_back(it.Get()); + if (!enabled_types.Has(it.Get())) { + node_lists.push_back(new base::ListValue()); + } else { + node_lists.push_back( + sync_manager_->GetAllNodesForType(it.Get()).release()); + } + } + + task_runner->PostTask( + FROM_HERE, + base::Bind(callback, types_vector, base::Passed(&node_lists))); +} + void SyncBackendHostCore::StartSavingChanges() { // We may already be shut down. if (!sync_loop_) diff --git a/chrome/browser/sync/glue/sync_backend_host_core.h b/chrome/browser/sync/glue/sync_backend_host_core.h index 408c3ab..d458d40 100644 --- a/chrome/browser/sync/glue/sync_backend_host_core.h +++ b/chrome/browser/sync/glue/sync_backend_host_core.h @@ -227,6 +227,12 @@ class SyncBackendHostCore return &release_request_context_signal_; } + void GetAllNodesForTypes( + syncer::ModelTypeSet types, + scoped_refptr<base::SequencedTaskRunner> task_runner, + base::Callback<void(const std::vector<syncer::ModelType>& type, + ScopedVector<base::ListValue>) > callback); + private: friend class base::RefCountedThreadSafe<SyncBackendHostCore>; friend class SyncBackendHostForProfileSyncTest; diff --git a/chrome/browser/sync/glue/sync_backend_host_impl.cc b/chrome/browser/sync/glue/sync_backend_host_impl.cc index 4dce302..5049879 100644 --- a/chrome/browser/sync/glue/sync_backend_host_impl.cc +++ b/chrome/browser/sync/glue/sync_backend_host_impl.cc @@ -502,6 +502,20 @@ void SyncBackendHostImpl::DisableProtocolEventForwarding() { core_)); } +void SyncBackendHostImpl::GetAllNodesForTypes( + syncer::ModelTypeSet types, + base::Callback<void(const std::vector<syncer::ModelType>&, + ScopedVector<base::ListValue>)> callback) { + DCHECK(initialized()); + registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE, + base::Bind( + &SyncBackendHostCore::GetAllNodesForTypes, + core_, + types, + frontend_loop_->message_loop_proxy(), + callback)); +} + void SyncBackendHostImpl::InitCore(scoped_ptr<DoInitializeOptions> options) { registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE, base::Bind(&SyncBackendHostCore::DoInitialize, diff --git a/chrome/browser/sync/glue/sync_backend_host_impl.h b/chrome/browser/sync/glue/sync_backend_host_impl.h index 3a35a16..84f9491 100644 --- a/chrome/browser/sync/glue/sync_backend_host_impl.h +++ b/chrome/browser/sync/glue/sync_backend_host_impl.h @@ -127,6 +127,10 @@ class SyncBackendHostImpl virtual SyncedDeviceTracker* GetSyncedDeviceTracker() const OVERRIDE; virtual void RequestBufferedProtocolEventsAndEnableForwarding() OVERRIDE; virtual void DisableProtocolEventForwarding() OVERRIDE; + virtual void GetAllNodesForTypes( + syncer::ModelTypeSet types, + base::Callback<void(const std::vector<syncer::ModelType>&, + ScopedVector<base::ListValue>)> type) OVERRIDE; virtual base::MessageLoop* GetSyncLoopForTesting() OVERRIDE; protected: diff --git a/chrome/browser/sync/glue/sync_backend_host_mock.cc b/chrome/browser/sync/glue/sync_backend_host_mock.cc index 2f9d5aa..21eeedb8 100644 --- a/chrome/browser/sync/glue/sync_backend_host_mock.cc +++ b/chrome/browser/sync/glue/sync_backend_host_mock.cc @@ -118,6 +118,11 @@ void SyncBackendHostMock::RequestBufferedProtocolEventsAndEnableForwarding() {} void SyncBackendHostMock::DisableProtocolEventForwarding() {} +void SyncBackendHostMock::GetAllNodesForTypes( + syncer::ModelTypeSet types, + base::Callback<void(const std::vector<syncer::ModelType>& type, + ScopedVector<base::ListValue>) > callback) {} + void SyncBackendHostMock::set_fail_initial_download(bool should_fail) { fail_initial_download_ = should_fail; } diff --git a/chrome/browser/sync/glue/sync_backend_host_mock.h b/chrome/browser/sync/glue/sync_backend_host_mock.h index ee477b0..60af243 100644 --- a/chrome/browser/sync/glue/sync_backend_host_mock.h +++ b/chrome/browser/sync/glue/sync_backend_host_mock.h @@ -98,6 +98,11 @@ class SyncBackendHostMock : public SyncBackendHost { virtual void RequestBufferedProtocolEventsAndEnableForwarding() OVERRIDE; virtual void DisableProtocolEventForwarding() OVERRIDE; + virtual void GetAllNodesForTypes( + syncer::ModelTypeSet types, + base::Callback<void(const std::vector<syncer::ModelType>& type, + ScopedVector<base::ListValue>) > callback) OVERRIDE; + virtual base::MessageLoop* GetSyncLoopForTesting() OVERRIDE; void set_fail_initial_download(bool should_fail); diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc index 2a6ccef..fce9958 100644 --- a/chrome/browser/sync/profile_sync_service.cc +++ b/chrome/browser/sync/profile_sync_service.cc @@ -83,7 +83,6 @@ #include "sync/internal_api/public/sync_encryption_handler.h" #include "sync/internal_api/public/util/experiments.h" #include "sync/internal_api/public/util/sync_string_conversions.h" -#include "sync/js/js_arg_list.h" #include "sync/js/js_event_details.h" #include "sync/util/cryptographer.h" #include "ui/base/l10n/l10n_util.h" @@ -2123,6 +2122,104 @@ void ProfileSyncService::RemoveProtocolEventObserver( } } +namespace { + +class GetAllNodesRequestHelper + : public base::RefCountedThreadSafe<GetAllNodesRequestHelper> { + public: + GetAllNodesRequestHelper( + syncer::ModelTypeSet requested_types, + const base::Callback<void(scoped_ptr<base::ListValue>)>& callback); + + void OnReceivedNodesForTypes( + const std::vector<syncer::ModelType>& types, + ScopedVector<base::ListValue> scoped_node_lists); + + private: + friend class base::RefCountedThreadSafe<GetAllNodesRequestHelper>; + virtual ~GetAllNodesRequestHelper(); + + scoped_ptr<base::ListValue> result_accumulator_; + + syncer::ModelTypeSet awaiting_types_; + base::Callback<void(scoped_ptr<base::ListValue>)> callback_; +}; + +GetAllNodesRequestHelper::GetAllNodesRequestHelper( + syncer::ModelTypeSet requested_types, + const base::Callback<void(scoped_ptr<base::ListValue>)>& callback) + : result_accumulator_(new base::ListValue()), + awaiting_types_(requested_types), + callback_(callback) {} + +GetAllNodesRequestHelper::~GetAllNodesRequestHelper() { + if (!awaiting_types_.Empty()) { + DLOG(WARNING) + << "GetAllNodesRequest deleted before request was fulfilled. " + << "Missing types are: " << ModelTypeSetToString(awaiting_types_); + } +} + +// Called when the set of nodes for a type or set of types has been returned. +// +// The nodes for several types can be returned at the same time by specifying +// their types in the |types| array, and putting their results at the +// correspnding indices in the |scoped_node_lists|. +void GetAllNodesRequestHelper::OnReceivedNodesForTypes( + const std::vector<syncer::ModelType>& types, + ScopedVector<base::ListValue> scoped_node_lists) { + DCHECK_EQ(types.size(), scoped_node_lists.size()); + + // Take unsafe ownership of the node list. + std::vector<base::ListValue*> node_lists; + scoped_node_lists.release(&node_lists); + + for (size_t i = 0; i < node_lists.size() && i < types.size(); ++i) { + const ModelType type = types[i]; + base::ListValue* node_list = node_lists[i]; + + // Add these results to our list. + scoped_ptr<base::DictionaryValue> type_dict(new base::DictionaryValue()); + type_dict->SetString("type", ModelTypeToString(type)); + type_dict->Set("nodes", node_list); + result_accumulator_->Append(type_dict.release()); + + // Remember that this part of the request is satisfied. + awaiting_types_.Remove(type); + } + + if (awaiting_types_.Empty()) { + callback_.Run(result_accumulator_.Pass()); + callback_.Reset(); + } +} + +} // namespace + +void ProfileSyncService::GetAllNodes( + const base::Callback<void(scoped_ptr<base::ListValue>)>& callback) { + // TODO(rlarocque): Should be GetRegisteredDirectoryTypes. + const ModelTypeSet directory_types = GetRegisteredDataTypes(); + scoped_refptr<GetAllNodesRequestHelper> helper = + new GetAllNodesRequestHelper(directory_types, callback); + + if (!backend_initialized_) { + // If there's no backend available to fulfill the request, handle it here. + ScopedVector<base::ListValue> empty_results; + std::vector<ModelType> type_vector; + for (ModelTypeSet::Iterator it = directory_types.First(); + it.Good(); it.Inc()) { + type_vector.push_back(it.Get()); + empty_results.push_back(new base::ListValue()); + } + helper->OnReceivedNodesForTypes(type_vector, empty_results.Pass()); + } else { + backend_->GetAllNodesForTypes( + directory_types, + base::Bind(&GetAllNodesRequestHelper::OnReceivedNodesForTypes, helper)); + } +} + bool ProfileSyncService::HasObserver( ProfileSyncServiceBase::Observer* observer) const { return observers_.HasObserver(observer); diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h index 228dfbb..12aa4b0 100644 --- a/chrome/browser/sync/profile_sync_service.h +++ b/chrome/browser/sync/profile_sync_service.h @@ -276,6 +276,15 @@ class ProfileSyncService : public ProfileSyncServiceBase, void RemoveProtocolEventObserver( browser_sync::ProtocolEventObserver* observer); + // Asynchronously fetches base::Value representations of all sync nodes and + // returns them to the specified callback on this thread. + // + // These requests can live a long time and return when you least expect it. + // For safety, the callback should be bound to some sort of WeakPtr<> or + // scoped_refptr<>. + void GetAllNodes( + const base::Callback<void(scoped_ptr<base::ListValue>)>& callback); + void RegisterAuthNotifications(); void UnregisterAuthNotifications(); diff --git a/chrome/browser/ui/webui/sync_internals_browsertest.js b/chrome/browser/ui/webui/sync_internals_browsertest.js index 3a1160c..a0dca23 100644 --- a/chrome/browser/ui/webui/sync_internals_browsertest.js +++ b/chrome/browser/ui/webui/sync_internals_browsertest.js @@ -60,112 +60,100 @@ SyncInternalsWebUITest.prototype = { * Constant hard-coded value to return from mock getAllNodes. * @const */ -var HARD_CODED_ALL_NODES = [ -{ - "BASE_SERVER_SPECIFICS": {}, - "BASE_VERSION": "1388699799780000", - "CTIME": "Wednesday, December 31, 1969 4:00:00 PM", - "ID": "sZ:ADqtAZw5kjSwSkukraMoMX6z0OlFXENzhA+1HZNcO6LbATQrkVenHJS5" + - "AgICYfj8/6KcvwlCw3FIvcRFtOEP3zSP5YJ1VH53/Q==", - "IS_DEL": false, - "IS_DIR": true, - "IS_UNAPPLIED_UPDATE": false, - "IS_UNSYNCED": false, - "LOCAL_EXTERNAL_ID": "0", - "META_HANDLE": "376", - "MTIME": "Wednesday, December 31, 1969 4:00:00 PM", - "NON_UNIQUE_NAME": "Typed URLs", - "PARENT_ID": "r", - "SERVER_CTIME": "Wednesday, December 31, 1969 4:00:00 PM", - "SERVER_IS_DEL": false, - "SERVER_IS_DIR": true, - "SERVER_MTIME": "Wednesday, December 31, 1969 4:00:00 PM", - "SERVER_NON_UNIQUE_NAME": "Typed URLs", - "SERVER_PARENT_ID": "r", - "SERVER_SPECIFICS": { - "typed_url": { - "visit_transitions": [], - "visits": [] - } - }, - "SERVER_UNIQUE_POSITION": "INVALID[]", - "SERVER_VERSION": "1388699799780000", - "SPECIFICS": { - "typed_url": { - "visit_transitions": [], - "visits": [] - } - }, - "SYNCING": false, - "TRANSACTION_VERSION": "1", - "UNIQUE_BOOKMARK_TAG": "", - "UNIQUE_CLIENT_TAG": "", - "UNIQUE_POSITION": "INVALID[]", - "UNIQUE_SERVER_TAG": "google_chrome_typed_urls", - "isDirty": false, - "serverModelType": "Typed URLs" -}, -{ - "BASE_SERVER_SPECIFICS": {}, - "BASE_VERSION": "1372291923970334", - "CTIME": "Wednesday, June 26, 2013 5:12:03 PM", - "ID": "sZ:ADqtAZyz70DhOIusPT1v2XCd/8YT8Fy43WlqdRyH6UwoBAqMkX5Pnkl/sW9A" + - "+AVrmzAPWFTrRBf0AWD57HyN4GcYXwSR9q4lYA==", - "IS_DEL": false, - "IS_DIR": false, - "IS_UNAPPLIED_UPDATE": false, - "IS_UNSYNCED": false, - "LOCAL_EXTERNAL_ID": "0", - "META_HANDLE": "3011", - "MTIME": "Wednesday, June 26, 2013 5:12:03 PM", - "NON_UNIQUE_NAME": "http://chrome.com/", - "PARENT_ID": "sZ:ADqtAZw5kjSwSkukraMoMX6z0OlFXENzhA+1HZNcO6LbATQrkVen" + - "HJS5AgICYfj8/6KcvwlCw3FIvcRFtOEP3zSP5YJ1VH53/Q==", - "SERVER_CTIME": "Wednesday, June 26, 2013 5:12:03 PM", - "SERVER_IS_DEL": false, - "SERVER_IS_DIR": false, - "SERVER_MTIME": "Wednesday, June 26, 2013 5:12:03 PM", - "SERVER_NON_UNIQUE_NAME": "http://chrome.com/", - "SERVER_PARENT_ID": "sZ:ADqtAZw5kjSwSkukraMoMX6z0OlFXENzhA+1HZNcO6LbAT" + - "QrkVenHJS5AgICYfj8/6KcvwlCw3FIvcRFtOEP3zSP5YJ1VH53/Q==", - "SERVER_SPECIFICS": { - "typed_url": { - "hidden": false, - "title": "Chrome", - "url": "http://chrome.com/", - "visit_transitions": [ - "268435457" - ], - "visits": [ - "13016765523677321" - ] - } - }, - "SERVER_UNIQUE_POSITION": "INVALID[]", - "SERVER_VERSION": "1372291923970334", - "SPECIFICS": { - "typed_url": { - "hidden": false, - "title": "Chrome", - "url": "http://chrome.com/", - "visit_transitions": [ - "268435457" - ], - "visits": [ - "13016765523677321" - ] - } - }, - "SYNCING": false, - "TRANSACTION_VERSION": "1", - "UNIQUE_BOOKMARK_TAG": "", - "UNIQUE_CLIENT_TAG": "J28uWKpXPuQwR3SJKbuLqzYGOcM=", - "UNIQUE_POSITION": "INVALID[]", - "UNIQUE_SERVER_TAG": "", - "isDirty": false, - "serverModelType": "Typed URLs" -} -]; +var HARD_CODED_ALL_NODES = [{ + "nodes": [{ + "ATTACHMENT_METADATA": "", + "BASE_SERVER_SPECIFICS": {}, + "BASE_VERSION": "1396470970810000", + "CTIME": "Wednesday, December 31, 1969 4:00:00 PM", + "ID": "sZ:ADqtAZwzF4GOIyvkI2enSI62AU5p/7MNmvuSSyf7yXJ1SkJwpp1YL" + + "6bbMkF8inzqW+EO6n2aPJ/uXccW9GHxorBlnKoZAWHVzg==", + "IS_DEL": false, + "IS_DIR": true, + "IS_UNAPPLIED_UPDATE": false, + "IS_UNSYNCED": false, + "LOCAL_EXTERNAL_ID": "0", + "META_HANDLE": "387", + "MTIME": "Wednesday, December 31, 1969 4:00:00 PM", + "NON_UNIQUE_NAME": "Autofill", + "PARENT_ID": "r", + "SERVER_CTIME": "Wednesday, December 31, 1969 4:00:00 PM", + "SERVER_IS_DEL": false, + "SERVER_IS_DIR": true, + "SERVER_MTIME": "Wednesday, December 31, 1969 4:00:00 PM", + "SERVER_NON_UNIQUE_NAME": "Autofill", + "SERVER_PARENT_ID": "r", + "SERVER_SPECIFICS": { + "autofill": { + "usage_timestamp": [] + } + }, + "SERVER_UNIQUE_POSITION": "INVALID[]", + "SERVER_VERSION": "1396470970810000", + "SPECIFICS": { + "autofill": { + "usage_timestamp": [] + } + }, + "SYNCING": false, + "TRANSACTION_VERSION": "1", + "UNIQUE_BOOKMARK_TAG": "", + "UNIQUE_CLIENT_TAG": "", + "UNIQUE_POSITION": "INVALID[]", + "UNIQUE_SERVER_TAG": "google_chrome_autofill", + "isDirty": false, + "serverModelType": "Autofill" + }, { + "ATTACHMENT_METADATA": "", + "BASE_SERVER_SPECIFICS": {}, + "BASE_VERSION": "1394241139528639", + "CTIME": "Friday, March 7, 2014 5:12:19 PM", + "ID": "sZ:ADqtAZwzc/ol1iaz+yNLjjWak9PBE0o/hATzpqJsyq/HX2xzV2f88" + + "FaOrT7HDE4tyn7zx2LWgkAFvZfCA5mOy4p0XFgiY0L+mw==", + "IS_DEL": false, + "IS_DIR": false, + "IS_UNAPPLIED_UPDATE": false, + "IS_UNSYNCED": false, + "LOCAL_EXTERNAL_ID": "0", + "META_HANDLE": "2989", + "MTIME": "Friday, March 7, 2014 5:12:19 PM", + "NON_UNIQUE_NAME": "autofill_entry|Email|rlsynctet2", + "PARENT_ID": "sZ:ADqtAZwzF4GOIyvkI2enSI62AU5p/7MNmvuSSyf7yXJ1Sk" + + "Jwpp1YL6bbMkF8inzqW+EO6n2aPJ/uXccW9GHxorBlnKoZAWHVzg==", + "SERVER_CTIME": "Friday, March 7, 2014 5:12:19 PM", + "SERVER_IS_DEL": false, + "SERVER_IS_DIR": false, + "SERVER_MTIME": "Friday, March 7, 2014 5:12:19 PM", + "SERVER_NON_UNIQUE_NAME": "autofill_entry|Email|rlsynctet2", + "SERVER_PARENT_ID": "sZ:ADqtAZwzF4GOIyvkI2enSI62AU5p/7MNmvuSSyf" + + "7yXJ1SkJwpp1YL6bbMkF8inzqW+EO6n2aPJ/uXccW9GHxorBlnKoZAWHVzg==", + "SERVER_SPECIFICS": { + "autofill": { + "name": "Email", + "usage_timestamp": ["13038713887000000", "13038713890000000"], + "value": "rlsynctet2" + } + }, + "SERVER_UNIQUE_POSITION": "INVALID[]", + "SERVER_VERSION": "1394241139528639", + "SPECIFICS": { + "autofill": { + "name": "Email", + "usage_timestamp": ["13038713887000000", "13038713890000000"], + "value": "rlsynctet2" + } + }, + "SYNCING": false, + "TRANSACTION_VERSION": "1", + "UNIQUE_BOOKMARK_TAG": "", + "UNIQUE_CLIENT_TAG": "EvliorKUf1rLjT+BGkNZp586Tsk=", + "UNIQUE_POSITION": "INVALID[]", + "UNIQUE_SERVER_TAG": "", + "isDirty": false, + "serverModelType": "Autofill" + }], + "type": "Autofill" +}]; /** * A value to return in mock onReceivedUpdatedAboutInfo event. @@ -301,10 +289,12 @@ TEST_F('SyncInternalsWebUITest', 'SearchTabDoesntChangeOnItemSelect', }); TEST_F('SyncInternalsWebUITest', 'NodeBrowserTest', function() { - this.mockHandler.expects(once()).getAllNodes([]).will( - callFunction(function() { - chrome.sync.getAllNodes.handleReply(HARD_CODED_ALL_NODES); - })); + var getAllNodesSavedArgs = new SaveMockArguments(); + this.mockHandler.expects(once()). + getAllNodes(getAllNodesSavedArgs.match(ANYTHING)). + will(callFunctionWithSavedArgs(getAllNodesSavedArgs, + chrome.sync.getAllNodesCallback, + HARD_CODED_ALL_NODES)); // Hit the refresh button. $('node-browser-refresh-button').click(); @@ -335,10 +325,12 @@ TEST_F('SyncInternalsWebUITest', 'NodeBrowserTest', function() { }); TEST_F('SyncInternalsWebUITest', 'NodeBrowserRefreshOnTabSelect', function() { - this.mockHandler.expects(once()).getAllNodes([]).will( - callFunction(function() { - chrome.sync.getAllNodes.handleReply(HARD_CODED_ALL_NODES); - })); + var getAllNodesSavedArgs = new SaveMockArguments(); + this.mockHandler.expects(once()). + getAllNodes(getAllNodesSavedArgs.match(ANYTHING)). + will(callFunctionWithSavedArgs(getAllNodesSavedArgs, + chrome.sync.getAllNodesCallback, + HARD_CODED_ALL_NODES)); // Should start with non-refreshed node browser. expectEquals($('node-browser-refresh-time').textContent, 'Never'); diff --git a/chrome/browser/ui/webui/sync_internals_message_handler.cc b/chrome/browser/ui/webui/sync_internals_message_handler.cc index e7869c2..3d4ddefc 100644 --- a/chrome/browser/ui/webui/sync_internals_message_handler.cc +++ b/chrome/browser/ui/webui/sync_internals_message_handler.cc @@ -15,12 +15,9 @@ #include "content/public/browser/web_ui.h" #include "sync/internal_api/public/events/protocol_event.h" #include "sync/internal_api/public/util/weak_handle.h" -#include "sync/js/js_arg_list.h" #include "sync/js/js_event_details.h" -using syncer::JsArgList; using syncer::JsEventDetails; -using syncer::JsReplyHandler; using syncer::ModelTypeSet; using syncer::WeakHandle; @@ -56,7 +53,10 @@ void SyncInternalsMessageHandler::RegisterMessages() { base::Bind(&SyncInternalsMessageHandler::HandleRequestListOfTypes, base::Unretained(this))); - RegisterJsControllerCallback("getAllNodes"); + web_ui()->RegisterMessageCallback( + "getAllNodes", + base::Bind(&SyncInternalsMessageHandler::HandleGetAllNodes, + base::Unretained(this))); } void SyncInternalsMessageHandler::HandleRegisterForEvents( @@ -95,14 +95,30 @@ void SyncInternalsMessageHandler::HandleRequestListOfTypes( event_details); } -void SyncInternalsMessageHandler::HandleJsReply( - const std::string& name, const JsArgList& args) { - DVLOG(1) << "Handling reply for " << name << " message" - << " with args " << args.ToString(); - const std::string& reply_handler = "chrome.sync." + name + ".handleReply"; - std::vector<const base::Value*> arg_list(args.Get().begin(), - args.Get().end()); - web_ui()->CallJavascriptFunction(reply_handler, arg_list); +void SyncInternalsMessageHandler::HandleGetAllNodes( + const base::ListValue* args) { + DCHECK_EQ(1U, args->GetSize()); + int request_id = 0; + bool success = args->GetInteger(0, &request_id); + DCHECK(success); + + ProfileSyncService* service = GetProfileSyncService(); + if (service) { + service->GetAllNodes( + base::Bind(&SyncInternalsMessageHandler::OnReceivedAllNodes, + weak_ptr_factory_.GetWeakPtr(), request_id)); + } +} + +void SyncInternalsMessageHandler::OnReceivedAllNodes( + int request_id, + scoped_ptr<base::ListValue> nodes) { + base::ListValue response_args; + response_args.Append(new base::FundamentalValue(request_id)); + response_args.Append(nodes.release()); + + web_ui()->CallJavascriptFunction("chrome.sync.getAllNodesCallback", + response_args); } void SyncInternalsMessageHandler::OnStateChanged() { @@ -129,15 +145,6 @@ void SyncInternalsMessageHandler::HandleJsEvent( details.Get()); } -void SyncInternalsMessageHandler::RegisterJsControllerCallback( - const std::string& name) { - web_ui()->RegisterMessageCallback( - name, - base::Bind(&SyncInternalsMessageHandler::ForwardToJsController, - base::Unretained(this), - name)); -} - void SyncInternalsMessageHandler::SendAboutInfo() { scoped_ptr<base::DictionaryValue> value = sync_ui_util::ConstructAboutInformation(GetProfileSyncService()); @@ -147,20 +154,6 @@ void SyncInternalsMessageHandler::SendAboutInfo() { *value); } -void SyncInternalsMessageHandler::ForwardToJsController( - const std::string& name, - const base::ListValue* args) { - if (js_controller_) { - scoped_ptr<base::ListValue> args_copy(args->DeepCopy()); - JsArgList js_arg_list(args_copy.get()); - js_controller_->ProcessJsMessage( - name, js_arg_list, - MakeWeakHandle(weak_ptr_factory_.GetWeakPtr())); - } else { - DLOG(WARNING) << "No sync service; dropping message " << name; - } -} - // Gets the ProfileSyncService of the underlying original profile. // May return NULL (e.g., if sync is disabled on the command line). ProfileSyncService* SyncInternalsMessageHandler::GetProfileSyncService() { diff --git a/chrome/browser/ui/webui/sync_internals_message_handler.h b/chrome/browser/ui/webui/sync_internals_message_handler.h index 80cc63a..971374a 100644 --- a/chrome/browser/ui/webui/sync_internals_message_handler.h +++ b/chrome/browser/ui/webui/sync_internals_message_handler.h @@ -17,7 +17,6 @@ #include "content/public/browser/web_ui_message_handler.h" #include "sync/js/js_controller.h" #include "sync/js/js_event_handler.h" -#include "sync/js/js_reply_handler.h" class ProfileSyncService; @@ -25,7 +24,6 @@ class ProfileSyncService; class SyncInternalsMessageHandler : public content::WebUIMessageHandler, public syncer::JsEventHandler, - public syncer::JsReplyHandler, public ProfileSyncServiceObserver, public browser_sync::ProtocolEventObserver { public: @@ -34,9 +32,6 @@ class SyncInternalsMessageHandler virtual void RegisterMessages() OVERRIDE; - // Forwards requests to the JsController. - void ForwardToJsController(const std::string& name, const base::ListValue*); - // Sets up observers to receive events and forward them to the UI. void HandleRegisterForEvents(const base::ListValue* args); @@ -46,15 +41,16 @@ class SyncInternalsMessageHandler // Fires and event to send the list of types back to the page. void HandleRequestListOfTypes(const base::ListValue* args); + // Handler for getAllNodes message. Needs a |request_id| argument. + void HandleGetAllNodes(const base::ListValue* args); + // syncer::JsEventHandler implementation. virtual void HandleJsEvent( const std::string& name, const syncer::JsEventDetails& details) OVERRIDE; - // syncer::JsReplyHandler implementation. - virtual void HandleJsReply( - const std::string& name, - const syncer::JsArgList& args) OVERRIDE; + // Callback used in GetAllNodes. + void OnReceivedAllNodes(int request_id, scoped_ptr<base::ListValue> nodes); // ProfileSyncServiceObserver implementation. virtual void OnStateChanged() OVERRIDE; @@ -63,9 +59,6 @@ class SyncInternalsMessageHandler virtual void OnProtocolEvent(const syncer::ProtocolEvent& e) OVERRIDE; private: - // Helper function to register JsController function callbacks. - void RegisterJsControllerCallback(const std::string& name); - // Fetches updated aboutInfo and sends it to the page in the form of an // onAboutInfoUpdated event. void SendAboutInfo(); diff --git a/sync/engine/directory_type_debug_info_emitter.cc b/sync/engine/directory_type_debug_info_emitter.cc new file mode 100644 index 0000000..6788786 --- /dev/null +++ b/sync/engine/directory_type_debug_info_emitter.cc @@ -0,0 +1,26 @@ +// Copyright 2014 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 "sync/engine/directory_type_debug_info_emitter.h" + +#include "sync/syncable/syncable_read_transaction.h" + +namespace syncer { + +DirectoryTypeDebugInfoEmitter::DirectoryTypeDebugInfoEmitter( + syncable::Directory* directory, + syncer::ModelType type) + : directory_(directory), + type_(type) {} + +DirectoryTypeDebugInfoEmitter::~DirectoryTypeDebugInfoEmitter() {} + +scoped_ptr<base::ListValue> DirectoryTypeDebugInfoEmitter::GetAllNodes() { + syncable::ReadTransaction trans(FROM_HERE, directory_); + scoped_ptr<base::ListValue> nodes( + directory_->GetNodeDetailsForType(&trans, type_)); + return nodes.Pass(); +} + +} // namespace syncer diff --git a/sync/engine/directory_type_debug_info_emitter.h b/sync/engine/directory_type_debug_info_emitter.h new file mode 100644 index 0000000..d2247dd --- /dev/null +++ b/sync/engine/directory_type_debug_info_emitter.h @@ -0,0 +1,34 @@ +// Copyright 2014 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 SYNC_ENGINE_DIRECTORY_TYPE_DEBUG_INFO_EMITTER_H_ +#define SYNC_ENGINE_DIRECTORY_TYPE_DEBUG_INFO_EMITTER_H_ + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/values.h" +#include "sync/syncable/directory.h" + +namespace syncer { + +// Supports debugging requests for a certain directory type. +class DirectoryTypeDebugInfoEmitter { + public: + DirectoryTypeDebugInfoEmitter(syncable::Directory* directory, + syncer::ModelType type); + virtual ~DirectoryTypeDebugInfoEmitter(); + + // Returns a ListValue representation of all known nodes of this type. + scoped_ptr<base::ListValue> GetAllNodes(); + + private: + syncable::Directory* directory_; + ModelType type_; + + DISALLOW_COPY_AND_ASSIGN(DirectoryTypeDebugInfoEmitter); +}; + +} // namespace syncer + +#endif // SYNC_ENGINE_DIRECTORY_TYPE_DEBUG_INFO_EMITTER_H_ diff --git a/sync/internal_api/public/sync_manager.h b/sync/internal_api/public/sync_manager.h index 0cdb599..d10b998 100644 --- a/sync/internal_api/public/sync_manager.h +++ b/sync/internal_api/public/sync_manager.h @@ -352,6 +352,9 @@ class SYNC_EXPORT SyncManager : public syncer::InvalidationHandler { // Returns the SyncManager's encryption handler. virtual SyncEncryptionHandler* GetEncryptionHandler() = 0; + virtual scoped_ptr<base::ListValue> GetAllNodesForType( + syncer::ModelType type) = 0; + // Ask the SyncManager to fetch updates for the given types. virtual void RefreshTypes(ModelTypeSet types) = 0; diff --git a/sync/internal_api/public/test/fake_sync_manager.h b/sync/internal_api/public/test/fake_sync_manager.h index 33d619a..fae4c8e 100644 --- a/sync/internal_api/public/test/fake_sync_manager.h +++ b/sync/internal_api/public/test/fake_sync_manager.h @@ -126,6 +126,8 @@ class FakeSyncManager : public SyncManager { virtual SyncEncryptionHandler* GetEncryptionHandler() OVERRIDE; virtual ScopedVector<syncer::ProtocolEvent> GetBufferedProtocolEvents() OVERRIDE; + virtual scoped_ptr<base::ListValue> GetAllNodesForType( + syncer::ModelType type) OVERRIDE; virtual void RefreshTypes(ModelTypeSet types) OVERRIDE; private: diff --git a/sync/internal_api/sync_manager_impl.cc b/sync/internal_api/sync_manager_impl.cc index 65d6176db..94dfc58 100644 --- a/sync/internal_api/sync_manager_impl.cc +++ b/sync/internal_api/sync_manager_impl.cc @@ -16,6 +16,7 @@ #include "base/observer_list.h" #include "base/strings/string_number_conversions.h" #include "base/values.h" +#include "sync/engine/directory_type_debug_info_emitter.h" #include "sync/engine/sync_scheduler.h" #include "sync/engine/syncer_types.h" #include "sync/internal_api/change_reorder_buffer.h" @@ -35,8 +36,6 @@ #include "sync/internal_api/sync_core.h" #include "sync/internal_api/syncapi_internal.h" #include "sync/internal_api/syncapi_server_connection_manager.h" -#include "sync/js/js_arg_list.h" -#include "sync/js/js_reply_handler.h" #include "sync/notifier/invalidation_util.h" #include "sync/notifier/invalidator.h" #include "sync/notifier/object_id_invalidation_map.h" @@ -175,11 +174,6 @@ SyncManagerImpl::SyncManagerImpl(const std::string& name) notification_info_map_.insert( std::make_pair(ModelTypeFromInt(i), NotificationInfo())); } - - // Bind message handlers. - BindJsMessageHandler( - "getAllNodes", - &SyncManagerImpl::GetAllNodes); } SyncManagerImpl::~SyncManagerImpl() { @@ -947,46 +941,27 @@ void SyncManagerImpl::SetJsEventHandler( js_sync_encryption_handler_observer_.SetJsEventHandler(event_handler); } +// TODO(rlarocque): This function is no longer needed and should be removed. +// See http://crbug.com/357821. void SyncManagerImpl::ProcessJsMessage( const std::string& name, const JsArgList& args, const WeakHandle<JsReplyHandler>& reply_handler) { - if (!initialized_) { - NOTREACHED(); - return; - } + NOTREACHED(); +} - if (!reply_handler.IsInitialized()) { - DVLOG(1) << "Uninitialized reply handler; dropping unknown message " - << name << " with args " << args.ToString(); - return; - } +scoped_ptr<base::ListValue> SyncManagerImpl::GetAllNodesForType( + syncer::ModelType type) { + DirectoryTypeDebugInfoEmitterMap* emitter_map = + model_type_registry_->directory_type_debug_info_emitter_map(); + DirectoryTypeDebugInfoEmitterMap::iterator it = emitter_map->find(type); - JsMessageHandler js_message_handler = js_message_handlers_[name]; - if (js_message_handler.is_null()) { - DVLOG(1) << "Dropping unknown message " << name - << " with args " << args.ToString(); - return; + if (it == emitter_map->end()) { + NOTREACHED() << "Asked to return debug info for invalid type " + << ModelTypeToString(type); + return scoped_ptr<base::ListValue>(); } - reply_handler.Call(FROM_HERE, - &JsReplyHandler::HandleJsReply, - name, js_message_handler.Run(args)); -} - -void SyncManagerImpl::BindJsMessageHandler( - const std::string& name, - UnboundJsMessageHandler unbound_message_handler) { - js_message_handlers_[name] = - base::Bind(unbound_message_handler, base::Unretained(this)); -} - -JsArgList SyncManagerImpl::GetAllNodes(const JsArgList& args) { - ReadTransaction trans(FROM_HERE, GetUserShare()); - base::ListValue return_args; - scoped_ptr<base::ListValue> nodes( - trans.GetDirectory()->GetAllNodeDetails(trans.GetWrappedTrans())); - return_args.Append(nodes.release()); - return JsArgList(&return_args); + return it->second->GetAllNodes(); } void SyncManagerImpl::OnInvalidatorStateChange(InvalidatorState state) { diff --git a/sync/internal_api/sync_manager_impl.h b/sync/internal_api/sync_manager_impl.h index f73a89d..52d382e 100644 --- a/sync/internal_api/sync_manager_impl.h +++ b/sync/internal_api/sync_manager_impl.h @@ -117,6 +117,8 @@ class SYNC_EXPORT_PRIVATE SyncManagerImpl : virtual SyncEncryptionHandler* GetEncryptionHandler() OVERRIDE; virtual ScopedVector<syncer::ProtocolEvent> GetBufferedProtocolEvents() OVERRIDE; + virtual scoped_ptr<base::ListValue> GetAllNodesForType( + syncer::ModelType type) OVERRIDE; // SyncEncryptionHandler::Observer implementation. virtual void OnPassphraseRequired( @@ -217,10 +219,6 @@ class SYNC_EXPORT_PRIVATE SyncManagerImpl : base::TimeDelta GetNudgeDelayTimeDelta(const ModelType& model_type); typedef std::map<ModelType, NotificationInfo> NotificationInfoMap; - typedef JsArgList (SyncManagerImpl::*UnboundJsMessageHandler)( - const JsArgList&); - typedef base::Callback<JsArgList(const JsArgList&)> JsMessageHandler; - typedef std::map<std::string, JsMessageHandler> JsMessageHandlerMap; // Determine if the parents or predecessors differ between the old and new // versions of an entry. Note that a node's index may change without its @@ -266,16 +264,6 @@ class SYNC_EXPORT_PRIVATE SyncManagerImpl : // Checks for server reachabilty and requests a nudge. void OnNetworkConnectivityChangedImpl(); - // Helper function used only by the constructor. - void BindJsMessageHandler( - const std::string& name, UnboundJsMessageHandler unbound_message_handler); - - // JS message handlers. - JsArgList GetAllNodes(const JsArgList& args); - JsArgList GetNodeSummariesById(const JsArgList& args); - JsArgList GetNodeDetailsById(const JsArgList& args); - JsArgList GetChildNodeIds(const JsArgList& args); - syncable::Directory* directory(); base::FilePath database_path_; @@ -351,7 +339,6 @@ class SYNC_EXPORT_PRIVATE SyncManagerImpl : NotificationInfoMap notification_info_map_; // These are for interacting with chrome://sync-internals. - JsMessageHandlerMap js_message_handlers_; JsSyncManagerObserver js_sync_manager_observer_; JsMutationEventObserver js_mutation_event_observer_; JsSyncEncryptionHandlerObserver js_sync_encryption_handler_observer_; diff --git a/sync/internal_api/sync_manager_impl_unittest.cc b/sync/internal_api/sync_manager_impl_unittest.cc index 7da7070..a8ee0be 100644 --- a/sync/internal_api/sync_manager_impl_unittest.cc +++ b/sync/internal_api/sync_manager_impl_unittest.cc @@ -42,10 +42,8 @@ #include "sync/internal_api/sync_encryption_handler_impl.h" #include "sync/internal_api/sync_manager_impl.h" #include "sync/internal_api/syncapi_internal.h" -#include "sync/js/js_arg_list.h" #include "sync/js/js_backend.h" #include "sync/js/js_event_handler.h" -#include "sync/js/js_reply_handler.h" #include "sync/js/js_test_util.h" #include "sync/notifier/fake_invalidation_handler.h" #include "sync/notifier/invalidation_handler.h" @@ -754,6 +752,7 @@ class SyncManagerTest : public testing::Test, sync_manager_.GetUserShare(), i->first); } } + PumpLoop(); } @@ -836,13 +835,6 @@ class SyncManagerTest : public testing::Test, message_loop_.RunUntilIdle(); } - void SendJsMessage(const std::string& name, const JsArgList& args, - const WeakHandle<JsReplyHandler>& reply_handler) { - js_backend_.Call(FROM_HERE, &JsBackend::ProcessJsMessage, - name, args, reply_handler); - PumpLoop(); - } - void SetJsEventHandler(const WeakHandle<JsEventHandler>& event_handler) { js_backend_.Call(FROM_HERE, &JsBackend::SetJsEventHandler, event_handler); @@ -938,42 +930,18 @@ class SyncManagerTest : public testing::Test, InternalComponentsFactory::Switches switches_; }; -TEST_F(SyncManagerTest, GetAllNodesTest) { - StrictMock<MockJsReplyHandler> reply_handler; - JsArgList return_args; +TEST_F(SyncManagerTest, GetAllNodesForTypeTest) { + ModelSafeRoutingInfo routing_info; + GetModelSafeRoutingInfo(&routing_info); + sync_manager_.StartSyncingNormally(routing_info); - EXPECT_CALL(reply_handler, - HandleJsReply("getAllNodes", _)) - .Times(1).WillRepeatedly(SaveArg<1>(&return_args)); + scoped_ptr<base::ListValue> node_list( + sync_manager_.GetAllNodesForType(syncer::PREFERENCES)); - { - base::ListValue args; - SendJsMessage("getAllNodes", - JsArgList(&args), reply_handler.AsWeakHandle()); - } - - // There's not much value in verifying every attribute on every node here. - // Most of the value of this test has already been achieved: we've verified we - // can call the above function without crashing or leaking memory. - // - // Let's just check the list size and a few of its elements. Anything more - // would make this test brittle without greatly increasing our chances of - // catching real bugs. + // Should have one node: the type root node. + ASSERT_EQ(1U, node_list->GetSize()); - const base::ListValue* node_list; const base::DictionaryValue* first_result; - - // The resulting argument list should have one argument, a list of nodes. - ASSERT_EQ(1U, return_args.Get().GetSize()); - ASSERT_TRUE(return_args.Get().GetList(0, &node_list)); - - // The database creation logic depends on the routing info. - // Refer to setup methods for more information. - ModelSafeRoutingInfo routes; - GetModelSafeRoutingInfo(&routes); - size_t directory_size = routes.size() + 1; - - ASSERT_EQ(directory_size, node_list->GetSize()); ASSERT_TRUE(node_list->GetDictionary(0, &first_result)); EXPECT_TRUE(first_result->HasKey("ID")); EXPECT_TRUE(first_result->HasKey("NON_UNIQUE_NAME")); diff --git a/sync/internal_api/test/fake_sync_manager.cc b/sync/internal_api/test/fake_sync_manager.cc index c7dd249..9f1abb8 100644 --- a/sync/internal_api/test/fake_sync_manager.cc +++ b/sync/internal_api/test/fake_sync_manager.cc @@ -244,6 +244,11 @@ FakeSyncManager::GetBufferedProtocolEvents() { return ScopedVector<syncer::ProtocolEvent>(); } +scoped_ptr<base::ListValue> FakeSyncManager::GetAllNodesForType( + syncer::ModelType type) { + return scoped_ptr<base::ListValue>(new base::ListValue()); +} + void FakeSyncManager::RefreshTypes(ModelTypeSet types) { last_refresh_request_types_ = types; } diff --git a/sync/sessions/model_type_registry.cc b/sync/sessions/model_type_registry.cc index b9d4114..fcf3996 100644 --- a/sync/sessions/model_type_registry.cc +++ b/sync/sessions/model_type_registry.cc @@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/message_loop/message_loop_proxy.h" #include "sync/engine/directory_commit_contributor.h" +#include "sync/engine/directory_type_debug_info_emitter.h" #include "sync/engine/directory_update_handler.h" #include "sync/engine/non_blocking_type_processor_core.h" #include "sync/internal_api/public/non_blocking_type_processor.h" @@ -34,14 +35,17 @@ void ModelTypeRegistry::SetEnabledDirectoryTypes( it.Good(); it.Inc()) { size_t result1 = update_handler_map_.erase(it.Get()); size_t result2 = commit_contributor_map_.erase(it.Get()); + size_t result3 = directory_type_debug_info_emitter_map_.erase(it.Get()); DCHECK_EQ(1U, result1); DCHECK_EQ(1U, result2); + DCHECK_EQ(1U, result3); } // Clear the old instances of directory update handlers and commit // contributors, deleting their contents in the processs. directory_update_handlers_.clear(); directory_commit_contributors_.clear(); + directory_type_debug_info_emitters_.clear(); // Create new ones and add them to the appropriate containers. for (ModelSafeRoutingInfo::const_iterator routing_iter = routing_info.begin(); @@ -57,10 +61,13 @@ void ModelTypeRegistry::SetEnabledDirectoryTypes( new DirectoryCommitContributor(directory_, type); DirectoryUpdateHandler* updater = new DirectoryUpdateHandler(directory_, type, worker); + DirectoryTypeDebugInfoEmitter* emitter = + new DirectoryTypeDebugInfoEmitter(directory_, type); // These containers take ownership of their contents. directory_commit_contributors_.push_back(committer); directory_update_handlers_.push_back(updater); + directory_type_debug_info_emitters_.push_back(emitter); bool inserted1 = update_handler_map_.insert(std::make_pair(type, updater)).second; @@ -69,6 +76,11 @@ void ModelTypeRegistry::SetEnabledDirectoryTypes( bool inserted2 = commit_contributor_map_.insert(std::make_pair(type, committer)).second; DCHECK(inserted2) << "Attempt to override existing type handler in map"; + + bool inserted3 = + directory_type_debug_info_emitter_map_.insert( + std::make_pair(type, emitter)).second; + DCHECK(inserted3) << "Attempt to override existing type handler in map"; } enabled_directory_types_ = GetRoutingInfoTypes(routing_info); @@ -142,6 +154,11 @@ CommitContributorMap* ModelTypeRegistry::commit_contributor_map() { return &commit_contributor_map_; } +DirectoryTypeDebugInfoEmitterMap* +ModelTypeRegistry::directory_type_debug_info_emitter_map() { + return &directory_type_debug_info_emitter_map_; +} + ModelTypeSet ModelTypeRegistry::GetEnabledDirectoryTypes() const { return enabled_directory_types_; } diff --git a/sync/sessions/model_type_registry.h b/sync/sessions/model_type_registry.h index 1317a6a..71d304f 100644 --- a/sync/sessions/model_type_registry.h +++ b/sync/sessions/model_type_registry.h @@ -23,12 +23,15 @@ class Directory; class CommitContributor; class DirectoryCommitContributor; class DirectoryUpdateHandler; +class DirectoryTypeDebugInfoEmitter; class NonBlockingTypeProcessorCore; class NonBlockingTypeProcessor; class UpdateHandler; typedef std::map<ModelType, UpdateHandler*> UpdateHandlerMap; typedef std::map<ModelType, CommitContributor*> CommitContributorMap; +typedef std::map<ModelType, DirectoryTypeDebugInfoEmitter*> + DirectoryTypeDebugInfoEmitterMap; // Keeps track of the sets of active update handlers and commit contributors. class SYNC_EXPORT_PRIVATE ModelTypeRegistry { @@ -67,6 +70,7 @@ class SYNC_EXPORT_PRIVATE ModelTypeRegistry { // Simple getters. UpdateHandlerMap* update_handler_map(); CommitContributorMap* commit_contributor_map(); + DirectoryTypeDebugInfoEmitterMap* directory_type_debug_info_emitter_map(); private: ModelTypeSet GetEnabledNonBlockingTypes() const; @@ -75,6 +79,9 @@ class SYNC_EXPORT_PRIVATE ModelTypeRegistry { // Sets of handlers and contributors. ScopedVector<DirectoryCommitContributor> directory_commit_contributors_; ScopedVector<DirectoryUpdateHandler> directory_update_handlers_; + ScopedVector<DirectoryTypeDebugInfoEmitter> + directory_type_debug_info_emitters_; + ScopedVector<NonBlockingTypeProcessorCore> non_blocking_type_processor_cores_; // Maps of UpdateHandlers and CommitContributors. @@ -82,6 +89,11 @@ class SYNC_EXPORT_PRIVATE ModelTypeRegistry { UpdateHandlerMap update_handler_map_; CommitContributorMap commit_contributor_map_; + // Map of DebugInfoEmitters for directory types. + // Non-blocking types handle debug info differently. + // Does not own its contents. + DirectoryTypeDebugInfoEmitterMap directory_type_debug_info_emitter_map_; + // The known ModelSafeWorkers. std::map<ModelSafeGroup, scoped_refptr<ModelSafeWorker> > workers_map_; diff --git a/sync/sync_core.gypi b/sync/sync_core.gypi index 0c263cb..4ba949c 100644 --- a/sync/sync_core.gypi +++ b/sync/sync_core.gypi @@ -54,6 +54,8 @@ 'engine/directory_commit_contributor.h', 'engine/directory_update_handler.cc', 'engine/directory_update_handler.h', + 'engine/directory_type_debug_info_emitter.cc', + 'engine/directory_type_debug_info_emitter.h', 'engine/get_commit_ids.cc', 'engine/get_commit_ids.h', 'engine/get_updates_delegate.cc', diff --git a/sync/syncable/directory.cc b/sync/syncable/directory.cc index 88fe94a..193a538 100644 --- a/sync/syncable/directory.cc +++ b/sync/syncable/directory.cc @@ -950,13 +950,18 @@ void Directory::CollectMetaHandleCounts( } } -scoped_ptr<base::ListValue> Directory::GetAllNodeDetails( - BaseTransaction* trans) { +scoped_ptr<base::ListValue> Directory::GetNodeDetailsForType( + BaseTransaction* trans, + ModelType type) { scoped_ptr<base::ListValue> nodes(new base::ListValue()); ScopedKernelLock lock(this); for (MetahandlesMap::iterator it = kernel_->metahandles_map.begin(); it != kernel_->metahandles_map.end(); ++it) { + if (GetModelTypeFromSpecifics(it->second->ref(SPECIFICS)) != type) { + continue; + } + EntryKernel* kernel = it->second; scoped_ptr<base::DictionaryValue> node( kernel->ToValue(GetCryptographer(trans))); diff --git a/sync/syncable/directory.h b/sync/syncable/directory.h index 5efa348..07e66e6 100644 --- a/sync/syncable/directory.h +++ b/sync/syncable/directory.h @@ -337,7 +337,10 @@ class SYNC_EXPORT Directory { void CollectMetaHandleCounts(std::vector<int>* num_entries_by_type, std::vector<int>* num_to_delete_entries_by_type); - scoped_ptr<base::ListValue> GetAllNodeDetails(BaseTransaction* trans); + // Returns a ListValue serialization of all nodes for the given type. + scoped_ptr<base::ListValue> GetNodeDetailsForType( + BaseTransaction* trans, + ModelType type); // Sets the level of invariant checking performed after transactions. void SetInvariantCheckLevel(InvariantCheckLevel check_level); |