summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/resources/sync_internals/chrome_sync.js10
-rw-r--r--chrome/browser/resources/sync_internals/data.js15
-rw-r--r--chrome/browser/resources/sync_internals/node_browser.html96
-rw-r--r--chrome/browser/resources/sync_internals/node_browser.js6
-rw-r--r--chrome/browser/resources/sync_internals/sync_node_browser.css23
-rw-r--r--chrome/browser/resources/sync_internals/sync_node_browser.js254
-rw-r--r--chrome/browser/resources/sync_internals_resources.grd1
-rw-r--r--chrome/browser/ui/webui/sync_internals_browsertest.js166
-rw-r--r--chrome/browser/ui/webui/sync_internals_message_handler.cc26
-rw-r--r--chrome/browser/ui/webui/sync_internals_message_handler.h1
-rw-r--r--chrome/browser/ui/webui/sync_internals_ui.cc2
11 files changed, 395 insertions, 205 deletions
diff --git a/chrome/browser/resources/sync_internals/chrome_sync.js b/chrome/browser/resources/sync_internals/chrome_sync.js
index 659f78b..fbbada0 100644
--- a/chrome/browser/resources/sync_internals/chrome_sync.js
+++ b/chrome/browser/resources/sync_internals/chrome_sync.js
@@ -146,15 +146,13 @@ var syncFunctions = [
'getNotificationState',
'getNotificationInfo',
+ // Get a static list of available data types.
+ 'getListOfTypes',
+
// Client server communication logging functions.
'getClientServerTraffic',
- // Node lookup functions. See chrome/browser/sync/engine/syncapi.h
- // for docs.
- 'getRootNodeDetails',
- 'getNodeSummariesById',
- 'getNodeDetailsById',
- 'getChildNodeIds',
+ // Get an array containing a JSON representations of all known sync nodes.
'getAllNodes',
];
diff --git a/chrome/browser/resources/sync_internals/data.js b/chrome/browser/resources/sync_internals/data.js
index 471759e..0f5c088 100644
--- a/chrome/browser/resources/sync_internals/data.js
+++ b/chrome/browser/resources/sync_internals/data.js
@@ -164,19 +164,10 @@ function createTypesCheckboxes(types) {
});
}
-function populateDatatypes(childNodeSummaries) {
- var types = childNodeSummaries.map(function(n) {
- return n.type;
- });
- types = types.sort();
- createTypesCheckboxes(types);
-}
-
document.addEventListener('DOMContentLoaded', function() {
- chrome.sync.getRootNodeDetails(function(rootNode) {
- chrome.sync.getChildNodeIds(rootNode.id, function(childNodeIds) {
- chrome.sync.getNodeSummariesById(childNodeIds, populateDatatypes);
- });
+ chrome.sync.getListOfTypes(function(types) {
+ types.sort();
+ createTypesCheckboxes(types);
});
});
diff --git a/chrome/browser/resources/sync_internals/node_browser.html b/chrome/browser/resources/sync_internals/node_browser.html
index b1d9b6a..3b323b0 100644
--- a/chrome/browser/resources/sync_internals/node_browser.html
+++ b/chrome/browser/resources/sync_internals/node_browser.html
@@ -7,58 +7,52 @@ item detail on the lower right. -->
as its container (style.height=100% doesn't work). Also fix
behavior when tree is too tall (currently it makes you scroll the
entire page). -->
- <div id="sync-node-tree-container">
- <tree id="sync-node-tree" icon-visibility="parent"></tree>
+ <div id="sync-node-browser-refresher">
+ <button id="node-browser-refresh-button">Refresh</button>
+ <div id="node-refresh-status">
+ Last refresh time: <span id="node-browser-refresh-time">Never</span>
+ </div>
</div>
- <div id="sync-node-splitter"></div>
<div id="sync-node-browser-container">
- <table id="node-browser">
- <tr>
- <td>ID</td>
- <td jscontent="id"></td>
- </tr>
- <tr>
- <td>Modification Time</td>
- <td jscontent="modificationTime"></td>
- </tr>
- <tr>
- <td>Parent</td>
- <td jsContent="parentId"></td>
- </tr>
- <tr>
- <td>Is Folder</td>
- <td jscontent="isFolder"></td>
- </tr>
- <tr>
- <td>Title</td>
- <td jscontent="title"></td>
- </tr>
- <tr>
- <td>Type</td>
- <td jscontent="type"></td>
- </tr>
- <tr>
- <td>External ID</td>
- <td jscontent="externalId"></td>
- </tr>
- <tr>
- <td>Predecessor</td>
- <td jscontent="predecessorId"></td>
- </tr>
- <tr>
- <td>Successor</td>
- <td jscontent="successorId"></td>
- </tr>
- <tr>
- <td>First Child</td>
- <td jscontent="firstChildId"></td>
- </tr>
- <tr>
- <td>Entry</td>
- <td><pre jscontent="entry"></pre></td>
- </tr>
- </table>
+ <div id="sync-node-tree-container">
+ </div>
+ <div id="sync-node-splitter"></div>
+ <div id="node-details">
+ <table>
+ <tr>
+ <td>Title</td>
+ <td jscontent="NON_UNIQUE_NAME"></td>
+ </tr>
+ <tr>
+ <td>ID</td>
+ <td jscontent="ID"></td>
+ </tr>
+ <tr>
+ <td>Modification Time</td>
+ <td jscontent="MTIME"></td>
+ </tr>
+ <tr>
+ <td>Parent</td>
+ <td jscontent="PARENT_ID"></td>
+ </tr>
+ <tr>
+ <td>Is Folder</td>
+ <td jscontent="IS_DIR"></td>
+ </tr>
+ <tr>
+ <td>Type</td>
+ <td jscontent="serverModelType"></td>
+ </tr>
+ <tr>
+ <td>External ID</td>
+ <td jscontent="LOCAL_EXTERNAL_ID"></td>
+ </tr>
+ <tr jsdisplay="$this.hasOwnProperty('positionIndex')">
+ <td>Position Index</td>
+ <td jscontent="positionIndex"></td>
+ </tr>
+ </table>
+ <pre jscontent="JSON.stringify($this, null, 2)"></pre></td>
+ </div>
</div>
</div>
-
-<script src="chrome://sync-internals/node_browser.js"></script>
diff --git a/chrome/browser/resources/sync_internals/node_browser.js b/chrome/browser/resources/sync_internals/node_browser.js
deleted file mode 100644
index 03f561b..0000000
--- a/chrome/browser/resources/sync_internals/node_browser.js
+++ /dev/null
@@ -1,6 +0,0 @@
-// 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.
-
-chrome.sync.decorateSyncNodeBrowser('sync-node-tree');
-cr.ui.decorate('#sync-node-splitter', cr.ui.Splitter);
diff --git a/chrome/browser/resources/sync_internals/sync_node_browser.css b/chrome/browser/resources/sync_internals/sync_node_browser.css
index 33bec66..c669647 100644
--- a/chrome/browser/resources/sync_internals/sync_node_browser.css
+++ b/chrome/browser/resources/sync_internals/sync_node_browser.css
@@ -2,10 +2,16 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
-#sync-node-main {
+#sync-node-browser-refresher {
+ border-bottom: 1px rgb(160,160,160) solid;
+}
+
+#sync-node-browser-refresher > * {
+ display: inline-block;
+}
+
+#sync-node-browser-container {
display: -webkit-box;
- /* Should be > #sync-page's min-height. */
- /* TODO(akalin): Find a less hacky way to do this. */
height: 750px;
}
@@ -17,7 +23,6 @@
max-width: 50%;
min-width: 50px;
overflow: auto;
- padding: 5px;
width: 200px;
}
@@ -42,20 +47,22 @@
</if>
}
-#sync-node-browser-container {
+#sync-node-details-container {
-webkit-box-flex: 1;
height: 100%;
overflow: auto;
+ visibility: hidden; /* Element is invisible until first refresh. */
}
-#node-browser {
+#node-details {
width: 100%;
}
-#node-browser td {
+#node-details td {
vertical-align: top;
+ white-space: nowrap;
}
-#node-browser tr:nth-child(odd) {
+#node-details tr:nth-child(odd) {
background: rgb(239, 243, 255);
}
diff --git a/chrome/browser/resources/sync_internals/sync_node_browser.js b/chrome/browser/resources/sync_internals/sync_node_browser.js
index 8d1ff3d..d20b864 100644
--- a/chrome/browser/resources/sync_internals/sync_node_browser.js
+++ b/chrome/browser/resources/sync_internals/sync_node_browser.js
@@ -6,52 +6,83 @@
// require: cr/ui.js
// require: cr/ui/tree.js
-cr.define('chrome.sync', function() {
+(function() {
/**
- * Gets all children of the given node and passes it to the given
- * callback.
- * @param {string} id The id whose children we want.
- * @param {function(Array.<!Object>)} callback The callback to call
- * with the list of children summaries.
+ * A helper function to determine if a node is the root of its type.
+ *
+ * @param {!Object} node The node to check.
*/
- function getSyncNodeChildrenSummaries(id, callback) {
- var timer = chrome.sync.makeTimer();
- chrome.sync.getChildNodeIds(id, function(childNodeIds) {
- console.debug('getChildNodeIds took ' +
- timer.elapsedSeconds + 's to retrieve ' +
- childNodeIds.length + ' ids');
- timer = chrome.sync.makeTimer();
- chrome.sync.getNodeSummariesById(
- childNodeIds, function(childrenSummaries) {
- console.debug('getNodeSummariesById took ' +
- timer.elapsedSeconds + 's to retrieve summaries for ' +
- childrenSummaries.length + ' nodes');
- callback(childrenSummaries);
- });
- });
+ var isTypeRootNode = function(node) {
+ return node.PARENT_ID == 'r' && node.UNIQUE_SERVER_TAG != '';
+ }
+
+ /**
+ * A helper function to determine if a node is a child of the given parent.
+ *
+ * @param {string} parentId The ID of the parent.
+ * @param {!Object} node The node to check.
+ */
+ var isChildOf = function(parentId, node) {
+ return node.PARENT_ID == parentId;
+ }
+
+ /**
+ * A helper function to sort sync nodes.
+ *
+ * Sorts by position index if possible, falls back to sorting by name, and
+ * finally sorting by METAHANDLE.
+ *
+ * If this proves to be slow and expensive, we should experiment with moving
+ * this functionality to C++ instead.
+ */
+ var nodeComparator = function(nodeA, nodeB) {
+ if (nodeA.hasOwnProperty('positionIndex') &&
+ nodeB.hasOwnProperty('positionIndex')) {
+ return nodeA.positionIndex - nodeB.positionIndex;
+ } else if (nodeA.NON_UNIQUE_NAME != nodeB.NON_UNIQUE_NAME) {
+ return nodeA.NON_UNIQUE_NAME.localeCompare(nodeB.NON_UNIQUE_NAME);
+ } else {
+ return nodeA.METAHANDLE - nodeB.METAHANDLE;
+ }
+ }
+
+ /**
+ * Updates the node detail view with the details for the given node.
+ * @param {!Object} node The struct representing the node we want to display.
+ */
+ function updateNodeDetailView(node) {
+ var nodeDetailsView = $('node-details');
+ nodeDetailsView.hidden = false;
+ jstProcess(new JsEvalContext(node.entry_), nodeDetailsView);
+ }
+
+ /**
+ * Updates the 'Last refresh time' display.
+ * @param {string} The text to display.
+ */
+ function setLastRefreshTime(str) {
+ $('node-browser-refresh-time').textContent = str;
}
/**
* Creates a new sync node tree item.
- * @param {{id: string, title: string, isFolder: boolean}}
- * nodeSummary The nodeSummary object for the node (as returned
- * by chrome.sync.getNodeSummariesById()).
+ *
* @constructor
+ * @param {!Object} node The nodeDetails object for the node as returned by
+ * chrome.sync.getAllNodes().
* @extends {cr.ui.TreeItem}
*/
- var SyncNodeTreeItem = function(nodeSummary) {
- var treeItem = new cr.ui.TreeItem({
- id_: nodeSummary.id
- });
+ var SyncNodeTreeItem = function(node) {
+ var treeItem = new cr.ui.TreeItem();
treeItem.__proto__ = SyncNodeTreeItem.prototype;
- treeItem.label = nodeSummary.title;
- if (nodeSummary.isFolder) {
+ treeItem.entry_ = node;
+ treeItem.label = node.NON_UNIQUE_NAME;
+ if (node.IS_DIR) {
treeItem.mayHaveChildren_ = true;
- // Load children asynchronously on expand.
- // TODO(akalin): Add a throbber while loading?
- treeItem.triggeredLoad_ = false;
+ // Load children on expand.
+ treeItem.expanded_ = false;
treeItem.addEventListener('expand',
treeItem.handleExpand_.bind(treeItem));
} else {
@@ -64,55 +95,31 @@ cr.define('chrome.sync', function() {
__proto__: cr.ui.TreeItem.prototype,
/**
- * Retrieves the details for this node.
- * @param {function(Object)} callback The callback that will be
- * called with the node details, or null if it could not be
- * retrieved.
+ * Finds the children of this node and appends them to the tree.
*/
- getDetails: function(callback) {
- chrome.sync.getNodeDetailsById([this.id_], function(nodeDetails) {
- callback(nodeDetails[0] || null);
- });
- },
-
handleExpand_: function(event) {
- if (!this.triggeredLoad_) {
- getSyncNodeChildrenSummaries(this.id_, this.addChildNodes_.bind(this));
- this.triggeredLoad_ = true;
- }
- },
+ var treeItem = this;
- /**
- * Adds children from the list of children summaries.
- * @param {Array.<{id: string, title: string, isFolder: boolean}>}
- * childrenSummaries The list of children summaries with which
- * to create the child nodes.
- */
- addChildNodes_: function(childrenSummaries) {
- var timer = chrome.sync.makeTimer();
- for (var i = 0; i < childrenSummaries.length; ++i) {
- var childTreeItem = new SyncNodeTreeItem(childrenSummaries[i]);
- this.add(childTreeItem);
+ if (treeItem.expanded_) {
+ return;
}
- console.debug('adding ' + childrenSummaries.length +
- ' children took ' + timer.elapsedSeconds + 's');
- }
- };
+ treeItem.expanded_ = true;
- /**
- * Updates the node detail view with the details for the given node.
- * @param {!Object} nodeDetails The details for the node we want
- * to display.
- */
- function updateNodeDetailView(nodeDetails) {
- var nodeBrowser = document.getElementById('node-browser');
- // TODO(akalin): Write a nicer detail viewer.
- nodeDetails.entry = JSON.stringify(nodeDetails.entry, null, 2);
- jstProcess(new JsEvalContext(nodeDetails), nodeBrowser);
- }
+ var children = treeItem.tree.allNodes.filter(
+ isChildOf.bind(undefined, treeItem.entry_.ID));
+ children.sort(nodeComparator);
+
+ children.forEach(function(node) {
+ treeItem.add(new SyncNodeTreeItem(node));
+ });
+ },
+ };
/**
- * Creates a new sync node tree.
+ * Creates a new sync node tree. Technically, it's a forest since it each
+ * type has its own root node for its own tree, but it still looks and acts
+ * mostly like a tree.
+ *
* @param {Object=} opt_propertyBag Optional properties.
* @constructor
* @extends {cr.ui.Tree}
@@ -125,57 +132,78 @@ cr.define('chrome.sync', function() {
decorate: function() {
cr.ui.Tree.prototype.decorate.call(this);
this.addEventListener('change', this.handleChange_.bind(this));
- chrome.sync.getRootNodeDetails(this.makeRoot_.bind(this));
+ this.allNodes = [];
},
- /**
- * Creates the root of the tree.
- * @param {{id: string, title: string, isFolder: boolean}}
- * rootNodeSummary The summary info for the root node.
- */
- makeRoot_: function(rootNodeSummary) {
- // The root node usually doesn't have a title.
- rootNodeSummary.title = rootNodeSummary.title || 'Root';
- var rootTreeItem = new SyncNodeTreeItem(rootNodeSummary);
- this.add(rootTreeItem);
+ populate: function(nodes) {
+ var tree = this;
+
+ // We store the full set of nodes in the SyncNodeTree object.
+ tree.allNodes = nodes;
+
+ var roots = tree.allNodes.filter(isTypeRootNode);
+ roots.sort(nodeComparator);
+
+ roots.forEach(function(typeRoot) {
+ tree.add(new SyncNodeTreeItem(typeRoot));
+ });
},
handleChange_: function(event) {
if (this.selectedItem) {
- this.selectedItem.getDetails(updateNodeDetailView);
+ updateNodeDetailView(this.selectedItem);
}
}
};
- function decorateSyncNodeBrowser(syncNodeBrowser) {
- cr.ui.decorate(syncNodeBrowser, SyncNodeTree);
+ /**
+ * Clears any existing UI state. Useful prior to a refresh.
+ */
+ function clear() {
+ var treeContainer = $('sync-node-tree-container');
+ while (treeContainer.firstChild) {
+ treeContainer.removeChild(treeContainer.firstChild);
+ }
+
+ var nodeDetailsView = $('node-details');
+ nodeDetailsView.hidden = true;
}
- // This is needed because JsTemplate (which is needed by
- // updateNodeDetailView) is loaded at the end of the file after
- // everything else.
- //
- // TODO(akalin): Remove dependency on JsTemplate and get rid of
- // this.
- var domLoaded = false;
- var pendingSyncNodeBrowsers = [];
- function decorateSyncNodeBrowserAfterDOMLoad(id) {
- var e = document.getElementById(id);
- if (domLoaded) {
- decorateSyncNodeBrowser(e);
- } else {
- pendingSyncNodeBrowsers.push(e);
- }
+ /**
+ * Fetch the latest set of nodes and refresh the UI.
+ */
+ function refresh() {
+ $('node-browser-refresh-button').disabled = true;
+
+ clear();
+ setLastRefreshTime('In progress since ' + (new Date()).toLocaleString());
+
+ chrome.sync.getAllNodes(function(nodes) {
+ var treeContainer = $('sync-node-tree-container');
+ var tree = document.createElement('tree');
+ tree.setAttribute('id', 'sync-node-tree');
+ tree.setAttribute('icon-visibility', 'parent');
+ treeContainer.appendChild(tree);
+
+ cr.ui.decorate(tree, SyncNodeTree);
+ tree.populate(nodes);
+
+ setLastRefreshTime((new Date()).toLocaleString());
+ $('node-browser-refresh-button').disabled = false;
+ });
}
- document.addEventListener('DOMContentLoaded', function() {
- for (var i = 0; i < pendingSyncNodeBrowsers.length; ++i) {
- decorateSyncNodeBrowser(pendingSyncNodeBrowsers[i]);
- }
- domLoaded = true;
+ document.addEventListener('DOMContentLoaded', function(e) {
+ $('node-browser-refresh-button').addEventListener('click', refresh);
+ cr.ui.decorate('#sync-node-splitter', cr.ui.Splitter);
+
+ // Automatically trigger a refresh the first time this tab is selected.
+ $('sync-browser-tab').addEventListener('selectedChange', function f(e) {
+ if (this.selected) {
+ $('sync-browser-tab').removeEventListener('selectedChange', f);
+ refresh();
+ }
+ });
});
- return {
- decorateSyncNodeBrowser: decorateSyncNodeBrowserAfterDOMLoad
- };
-});
+})();
diff --git a/chrome/browser/resources/sync_internals_resources.grd b/chrome/browser/resources/sync_internals_resources.grd
index 3c8f32e..71fe6ab 100644
--- a/chrome/browser/resources/sync_internals_resources.grd
+++ b/chrome/browser/resources/sync_internals_resources.grd
@@ -22,7 +22,6 @@
<include name="IDR_SYNC_INTERNALS_EVENTS_JS" file="sync_internals/events.js" type="BINDATA" />
<include name="IDR_SYNC_INTERNALS_NOTIFICATIONS_JS" file="sync_internals/notifications.js" type="BINDATA" />
<include name="IDR_SYNC_INTERNALS_SEARCH_JS" file="sync_internals/search.js" type="BINDATA" />
- <include name="IDR_SYNC_INTERNALS_NODE_BROWSER_JS" file="sync_internals/node_browser.js" type="BINDATA" />
<include name="IDR_SYNC_INTERNALS_TRAFFIC_JS" file="sync_internals/traffic.js" type="BINDATA" />
</includes>
</release>
diff --git a/chrome/browser/ui/webui/sync_internals_browsertest.js b/chrome/browser/ui/webui/sync_internals_browsertest.js
index 5a261bf..733bac5 100644
--- a/chrome/browser/ui/webui/sync_internals_browsertest.js
+++ b/chrome/browser/ui/webui/sync_internals_browsertest.js
@@ -20,7 +20,9 @@ SyncInternalsWebUITest.prototype = {
/** @override */
preLoad: function() {
- // TODO(zea): mock out the the sync info to fake an active syncer.
+ this.makeAndRegisterMockHandler([
+ 'getAllNodes',
+ ]);
},
/**
@@ -48,6 +50,114 @@ SyncInternalsWebUITest.prototype = {
}
};
+/** Constant hard-coded value to return from mock getAllNodes */
+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"
+}
+];
+
TEST_F('SyncInternalsWebUITest', 'Uninitialized', function() {
assertNotEquals(null, chrome.sync.aboutInfo);
expectTrue(this.hasInDetails(true, 'Username', ''));
@@ -77,3 +187,57 @@ TEST_F('SyncInternalsWebUITest', 'SearchTabDoesntChangeOnItemSelect',
$('sync-results-list').getListItemByIndex(0).selected = true;
expectTrue($('sync-search-tab').selected);
});
+
+TEST_F('SyncInternalsWebUITest', 'NodeBrowserTest', function() {
+ this.mockHandler.expects(once()).getAllNodes([]).will(
+ callFunction(function() {
+ chrome.sync.getAllNodes.handleReply(HARD_CODED_ALL_NODES);
+ }));
+
+ // Hit the refresh button.
+ $('node-browser-refresh-button').click();
+
+ // Check that the refresh time was updated.
+ expectNotEquals($('node-browser-refresh-time').textContent, 'Never');
+
+ // Verify some hard-coded assumptions. These depend on the vaue of the
+ // hard-coded nodes, specified elsewhere in this file.
+
+ // Start with the tree itself.
+ var tree = $('sync-node-tree');
+ assertEquals(1, tree.items.length);
+
+ // Check the type root and expand it.
+ var typeRoot = tree.items[0];
+ expectFalse(typeRoot.expanded);
+ typeRoot.expanded = true;
+ assertEquals(1, typeRoot.items.length);
+
+ // An actual sync node. The child of the type root.
+ var leaf = typeRoot.items[0];
+
+ // Verify that selecting it affects the details view.
+ expectTrue($('node-details').hasAttribute('hidden'));
+ leaf.selected = true;
+ expectFalse($('node-details').hasAttribute('hidden'));
+});
+
+TEST_F('SyncInternalsWebUITest', 'NodeBrowserRefreshOnTabSelect', function() {
+ this.mockHandler.expects(once()).getAllNodes([]).will(
+ callFunction(function() {
+ chrome.sync.getAllNodes.handleReply(HARD_CODED_ALL_NODES);
+ }));
+
+ // Should start with non-refreshed node browser.
+ expectEquals($('node-browser-refresh-time').textContent, 'Never');
+
+ // Selecting the tab will refresh it.
+ $('sync-browser-tab').selected = true;
+ expectNotEquals($('node-browser-refresh-time').textContent, 'Never');
+
+ // Re-selecting the tab shouldn't re-refresh.
+ $('node-browser-refresh-time').textContent = 'TestCanary';
+ $('sync-browser-tab').selected = false;
+ $('sync-browser-tab').selected = true;
+ expectEquals($('node-browser-refresh-time').textContent, 'TestCanary');
+});
diff --git a/chrome/browser/ui/webui/sync_internals_message_handler.cc b/chrome/browser/ui/webui/sync_internals_message_handler.cc
index 88d7e29..1f03b59 100644
--- a/chrome/browser/ui/webui/sync_internals_message_handler.cc
+++ b/chrome/browser/ui/webui/sync_internals_message_handler.cc
@@ -19,6 +19,7 @@
using syncer::JsArgList;
using syncer::JsEventDetails;
using syncer::JsReplyHandler;
+using syncer::ModelTypeSet;
using syncer::WeakHandle;
SyncInternalsMessageHandler::SyncInternalsMessageHandler()
@@ -44,18 +45,19 @@ void SyncInternalsMessageHandler::RegisterMessages() {
base::Bind(&SyncInternalsMessageHandler::OnGetAboutInfo,
base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "getListOfTypes",
+ base::Bind(&SyncInternalsMessageHandler::OnGetListOfTypes,
+ base::Unretained(this)));
+
RegisterJsControllerCallback("getNotificationState");
RegisterJsControllerCallback("getNotificationInfo");
- RegisterJsControllerCallback("getRootNodeDetails");
- RegisterJsControllerCallback("getNodeSummariesById");
- RegisterJsControllerCallback("getNodeDetailsById");
RegisterJsControllerCallback("getAllNodes");
- RegisterJsControllerCallback("getChildNodeIds");
RegisterJsControllerCallback("getClientServerTraffic");
}
void SyncInternalsMessageHandler::OnGetAboutInfo(const base::ListValue* args) {
- // TODO(rlarocque): We should DCHECK(!args) here.
+ // TODO(rlarocque): We should DCHECK(!args) here. See crbug.com/334431.
scoped_ptr<base::DictionaryValue> value =
sync_ui_util::ConstructAboutInformation(GetProfileSyncService());
web_ui()->CallJavascriptFunction(
@@ -63,6 +65,20 @@ void SyncInternalsMessageHandler::OnGetAboutInfo(const base::ListValue* args) {
*value);
}
+void SyncInternalsMessageHandler::OnGetListOfTypes(
+ const base::ListValue* args) {
+ // TODO(rlarocque): We should DCHECK(!args) here. See crbug.com/334431.
+ base::ListValue type_list;
+ ModelTypeSet protocol_types = syncer::ProtocolTypes();
+ for (ModelTypeSet::Iterator it = protocol_types.First();
+ it.Good(); it.Inc()) {
+ type_list.Append(new base::StringValue(ModelTypeToString(it.Get())));
+ }
+ web_ui()->CallJavascriptFunction(
+ "chrome.sync.getListOfTypes.handleReply",
+ type_list);
+}
+
void SyncInternalsMessageHandler::HandleJsReply(
const std::string& name, const JsArgList& args) {
DVLOG(1) << "Handling reply for " << name << " message"
diff --git a/chrome/browser/ui/webui/sync_internals_message_handler.h b/chrome/browser/ui/webui/sync_internals_message_handler.h
index 6fd9714..5b652d5 100644
--- a/chrome/browser/ui/webui/sync_internals_message_handler.h
+++ b/chrome/browser/ui/webui/sync_internals_message_handler.h
@@ -31,6 +31,7 @@ class SyncInternalsMessageHandler
void ForwardToJsController(const std::string& name, const base::ListValue*);
void OnGetAboutInfo(const base::ListValue*);
+ void OnGetListOfTypes(const base::ListValue*);
// syncer::JsEventHandler implementation.
virtual void HandleJsEvent(
diff --git a/chrome/browser/ui/webui/sync_internals_ui.cc b/chrome/browser/ui/webui/sync_internals_ui.cc
index eda485b..baf4061 100644
--- a/chrome/browser/ui/webui/sync_internals_ui.cc
+++ b/chrome/browser/ui/webui/sync_internals_ui.cc
@@ -34,8 +34,6 @@ content::WebUIDataSource* CreateSyncInternalsHTMLSource() {
source->AddResourcePath("notifications.js",
IDR_SYNC_INTERNALS_NOTIFICATIONS_JS);
source->AddResourcePath("search.js", IDR_SYNC_INTERNALS_SEARCH_JS);
- source->AddResourcePath("node_browser.js",
- IDR_SYNC_INTERNALS_NODE_BROWSER_JS);
source->AddResourcePath("traffic.js", IDR_SYNC_INTERNALS_TRAFFIC_JS);
source->SetDefaultResource(IDR_SYNC_INTERNALS_INDEX_HTML);
return source;