Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1293)

Side by Side Diff: chrome/browser/resources/sync_internals/sync_node_browser.js

Issue 134443004: sync: Remove some WebUI debug functions (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // require: cr.js 5 // require: cr.js
6 // require: cr/ui.js 6 // require: cr/ui.js
7 // require: cr/ui/tree.js 7 // require: cr/ui/tree.js
8 8
9 cr.define('chrome.sync', function() { 9 (function() {
10 /** 10 /**
11 * Gets all children of the given node and passes it to the given 11 * A helper function to determine if a node is the root of its type.
12 * callback. 12 *
13 * @param {string} id The id whose children we want. 13 * @param {!Object} node The node to check.
14 * @param {function(Array.<!Object>)} callback The callback to call
15 * with the list of children summaries.
16 */ 14 */
17 function getSyncNodeChildrenSummaries(id, callback) { 15 var isTypeRootNode = function(node) {
18 var timer = chrome.sync.makeTimer(); 16 return node.PARENT_ID == 'r' && node.UNIQUE_SERVER_TAG != '';
19 chrome.sync.getChildNodeIds(id, function(childNodeIds) { 17 }
20 console.debug('getChildNodeIds took ' + 18
21 timer.elapsedSeconds + 's to retrieve ' + 19 /**
22 childNodeIds.length + ' ids'); 20 * A helper function to determine if a node is a child of the given parent.
23 timer = chrome.sync.makeTimer(); 21 *
24 chrome.sync.getNodeSummariesById( 22 * @param {string} parentId The ID of the parent.
25 childNodeIds, function(childrenSummaries) { 23 * @param {!Object} node The node to check.
26 console.debug('getNodeSummariesById took ' + 24 */
27 timer.elapsedSeconds + 's to retrieve summaries for ' + 25 var isChildOf = function(parentId, node) {
28 childrenSummaries.length + ' nodes'); 26 return node.PARENT_ID == parentId;
29 callback(childrenSummaries); 27 }
30 }); 28
31 }); 29 /**
30 * A helper function to sort sync nodes.
31 *
32 * Sorts by position index if possible, falls back to sorting by name, and
33 * finally sorting by METAHANDLE.
34 *
35 * If this proves to be slow and expensive, we should experiment with moving
36 * this functionality to C++ instead.
37 */
38 var nodeComparator = function(nodeA, nodeB) {
39 if (nodeA.hasOwnProperty('positionIndex') &&
40 nodeB.hasOwnProperty('positionIndex')) {
41 return nodeA.positionIndex - nodeB.positionIndex;
42 } else if (nodeA.NON_UNIQUE_NAME != nodeB.NON_UNIQUE_NAME) {
43 return nodeA.NON_UNIQUE_NAME.localeCompare(nodeB.NON_UNIQUE_NAME);
44 } else {
45 return nodeA.METAHANDLE - nodeB.METAHANDLE;
46 }
47 }
48
49 /**
50 * Updates the node detail view with the details for the given node.
51 * @param {!Object} node The struct representing the node we want to display.
52 */
53 function updateNodeDetailView(node) {
54 var nodeDetailsView = $('node-details');
55 nodeDetailsView.hidden = false;
56 jstProcess(new JsEvalContext(node.entry_), nodeDetailsView);
57 }
58
59 /**
60 * Updates the 'Last refresh time' display.
61 * @param {string} The text to display.
62 */
63 function setLastRefreshTime(str) {
64 $('node-browser-refresh-time').textContent = str;
32 } 65 }
33 66
34 /** 67 /**
35 * Creates a new sync node tree item. 68 * Creates a new sync node tree item.
36 * @param {{id: string, title: string, isFolder: boolean}} 69 *
37 * nodeSummary The nodeSummary object for the node (as returned
38 * by chrome.sync.getNodeSummariesById()).
39 * @constructor 70 * @constructor
71 * @param {!Object} node The nodeDetails object for the node as returned by
72 * chrome.sync.getAllNodes().
40 * @extends {cr.ui.TreeItem} 73 * @extends {cr.ui.TreeItem}
41 */ 74 */
42 var SyncNodeTreeItem = function(nodeSummary) { 75 var SyncNodeTreeItem = function(node) {
43 var treeItem = new cr.ui.TreeItem({ 76 var treeItem = new cr.ui.TreeItem();
44 id_: nodeSummary.id
45 });
46 treeItem.__proto__ = SyncNodeTreeItem.prototype; 77 treeItem.__proto__ = SyncNodeTreeItem.prototype;
47 78
48 treeItem.label = nodeSummary.title; 79 treeItem.entry_ = node;
49 if (nodeSummary.isFolder) { 80 treeItem.label = node.NON_UNIQUE_NAME;
81 if (node.IS_DIR) {
50 treeItem.mayHaveChildren_ = true; 82 treeItem.mayHaveChildren_ = true;
51 83
52 // Load children asynchronously on expand. 84 // Load children on expand.
53 // TODO(akalin): Add a throbber while loading? 85 treeItem.expanded_ = false;
54 treeItem.triggeredLoad_ = false;
55 treeItem.addEventListener('expand', 86 treeItem.addEventListener('expand',
56 treeItem.handleExpand_.bind(treeItem)); 87 treeItem.handleExpand_.bind(treeItem));
57 } else { 88 } else {
58 treeItem.classList.add('leaf'); 89 treeItem.classList.add('leaf');
59 } 90 }
60 return treeItem; 91 return treeItem;
61 }; 92 };
62 93
63 SyncNodeTreeItem.prototype = { 94 SyncNodeTreeItem.prototype = {
64 __proto__: cr.ui.TreeItem.prototype, 95 __proto__: cr.ui.TreeItem.prototype,
65 96
66 /** 97 /**
67 * Retrieves the details for this node. 98 * Finds the children of this node and appends them to the tree.
68 * @param {function(Object)} callback The callback that will be
69 * called with the node details, or null if it could not be
70 * retrieved.
71 */ 99 */
72 getDetails: function(callback) { 100 handleExpand_: function(event) {
73 chrome.sync.getNodeDetailsById([this.id_], function(nodeDetails) { 101 var treeItem = this;
74 callback(nodeDetails[0] || null); 102
103 if (treeItem.expanded_) {
104 return;
105 }
106 treeItem.expanded_ = true;
107
108 var children = treeItem.tree.allNodes.filter(
109 isChildOf.bind(undefined, treeItem.entry_.ID));
110 children.sort(nodeComparator);
111
112 children.forEach(function(node) {
113 treeItem.add(new SyncNodeTreeItem(node));
75 }); 114 });
76 }, 115 },
77
78 handleExpand_: function(event) {
79 if (!this.triggeredLoad_) {
80 getSyncNodeChildrenSummaries(this.id_, this.addChildNodes_.bind(this));
81 this.triggeredLoad_ = true;
82 }
83 },
84
85 /**
86 * Adds children from the list of children summaries.
87 * @param {Array.<{id: string, title: string, isFolder: boolean}>}
88 * childrenSummaries The list of children summaries with which
89 * to create the child nodes.
90 */
91 addChildNodes_: function(childrenSummaries) {
92 var timer = chrome.sync.makeTimer();
93 for (var i = 0; i < childrenSummaries.length; ++i) {
94 var childTreeItem = new SyncNodeTreeItem(childrenSummaries[i]);
95 this.add(childTreeItem);
96 }
97 console.debug('adding ' + childrenSummaries.length +
98 ' children took ' + timer.elapsedSeconds + 's');
99 }
100 }; 116 };
101 117
102 /** 118 /**
103 * Updates the node detail view with the details for the given node. 119 * Creates a new sync node tree. Technically, it's a forest since it each
104 * @param {!Object} nodeDetails The details for the node we want 120 * type has its own root node for its own tree, but it still looks and acts
105 * to display. 121 * mostly like a tree.
106 */ 122 *
107 function updateNodeDetailView(nodeDetails) {
108 var nodeBrowser = document.getElementById('node-browser');
109 // TODO(akalin): Write a nicer detail viewer.
110 nodeDetails.entry = JSON.stringify(nodeDetails.entry, null, 2);
111 jstProcess(new JsEvalContext(nodeDetails), nodeBrowser);
112 }
113
114 /**
115 * Creates a new sync node tree.
116 * @param {Object=} opt_propertyBag Optional properties. 123 * @param {Object=} opt_propertyBag Optional properties.
117 * @constructor 124 * @constructor
118 * @extends {cr.ui.Tree} 125 * @extends {cr.ui.Tree}
119 */ 126 */
120 var SyncNodeTree = cr.ui.define('tree'); 127 var SyncNodeTree = cr.ui.define('tree');
121 128
122 SyncNodeTree.prototype = { 129 SyncNodeTree.prototype = {
123 __proto__: cr.ui.Tree.prototype, 130 __proto__: cr.ui.Tree.prototype,
124 131
125 decorate: function() { 132 decorate: function() {
126 cr.ui.Tree.prototype.decorate.call(this); 133 cr.ui.Tree.prototype.decorate.call(this);
127 this.addEventListener('change', this.handleChange_.bind(this)); 134 this.addEventListener('change', this.handleChange_.bind(this));
128 chrome.sync.getRootNodeDetails(this.makeRoot_.bind(this)); 135 this.allNodes = [];
129 }, 136 },
130 137
131 /** 138 populate: function(nodes) {
132 * Creates the root of the tree. 139 var tree = this;
133 * @param {{id: string, title: string, isFolder: boolean}} 140
134 * rootNodeSummary The summary info for the root node. 141 // We store the full set of nodes in the SyncNodeTree object.
135 */ 142 tree.allNodes = nodes;
136 makeRoot_: function(rootNodeSummary) { 143
137 // The root node usually doesn't have a title. 144 var roots = tree.allNodes.filter(isTypeRootNode);
138 rootNodeSummary.title = rootNodeSummary.title || 'Root'; 145 roots.sort(nodeComparator);
139 var rootTreeItem = new SyncNodeTreeItem(rootNodeSummary); 146
140 this.add(rootTreeItem); 147 roots.forEach(function(typeRoot) {
148 tree.add(new SyncNodeTreeItem(typeRoot));
149 });
141 }, 150 },
142 151
143 handleChange_: function(event) { 152 handleChange_: function(event) {
144 if (this.selectedItem) { 153 if (this.selectedItem) {
145 this.selectedItem.getDetails(updateNodeDetailView); 154 updateNodeDetailView(this.selectedItem);
146 } 155 }
147 } 156 }
148 }; 157 };
149 158
150 function decorateSyncNodeBrowser(syncNodeBrowser) { 159 /**
151 cr.ui.decorate(syncNodeBrowser, SyncNodeTree); 160 * Clears any existing UI state. Useful prior to a refresh.
161 */
162 function clear() {
163 var treeContainer = $('sync-node-tree-container');
164 while (treeContainer.firstChild) {
165 treeContainer.removeChild(treeContainer.firstChild);
166 }
167
168 var nodeDetailsView = $('node-details');
169 nodeDetailsView.hidden = true;
152 } 170 }
153 171
154 // This is needed because JsTemplate (which is needed by 172 /**
155 // updateNodeDetailView) is loaded at the end of the file after 173 * Fetch the latest set of nodes and refresh the UI.
156 // everything else. 174 */
157 // 175 function refresh() {
158 // TODO(akalin): Remove dependency on JsTemplate and get rid of 176 $('node-browser-refresh-button').disabled = true;
159 // this. 177
160 var domLoaded = false; 178 clear();
161 var pendingSyncNodeBrowsers = []; 179 setLastRefreshTime('In progress since ' + (new Date()).toLocaleString());
162 function decorateSyncNodeBrowserAfterDOMLoad(id) { 180
163 var e = document.getElementById(id); 181 chrome.sync.getAllNodes(function(nodes) {
164 if (domLoaded) { 182 var treeContainer = $('sync-node-tree-container');
165 decorateSyncNodeBrowser(e); 183 var tree = document.createElement('tree');
166 } else { 184 tree.setAttribute('id', 'sync-node-tree');
167 pendingSyncNodeBrowsers.push(e); 185 tree.setAttribute('icon-visibility', 'parent');
168 } 186 treeContainer.appendChild(tree);
187
188 cr.ui.decorate(tree, SyncNodeTree);
189 tree.populate(nodes);
190
191 setLastRefreshTime((new Date()).toLocaleString());
192 $('node-browser-refresh-button').disabled = false;
193 });
169 } 194 }
170 195
171 document.addEventListener('DOMContentLoaded', function() { 196 document.addEventListener('DOMContentLoaded', function(e) {
172 for (var i = 0; i < pendingSyncNodeBrowsers.length; ++i) { 197 $('node-browser-refresh-button').addEventListener('click', refresh);
173 decorateSyncNodeBrowser(pendingSyncNodeBrowsers[i]); 198 cr.ui.decorate('#sync-node-splitter', cr.ui.Splitter);
174 } 199
175 domLoaded = true; 200 // Automatically trigger a refresh the first time this tab is selected.
201 $('sync-browser-tab').addEventListener('selectedChange', function f(e) {
202 if (this.selected) {
203 $('sync-browser-tab').removeEventListener('selectedChange', f);
204 refresh();
205 }
206 });
176 }); 207 });
177 208
178 return { 209 })();
179 decorateSyncNodeBrowser: decorateSyncNodeBrowserAfterDOMLoad
180 };
181 });
OLDNEW
« no previous file with comments | « chrome/browser/resources/sync_internals/sync_node_browser.css ('k') | chrome/browser/resources/sync_internals_resources.grd » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698