Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / chrome / browser / resources / sync_internals / sync_search.js
blob48c0e081607ae0bdac3d7ad011318334c3fe4a15
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // require: cr.js
7 cr.define('chrome.sync', function() {
8   var currSearchId = 0;
10   var setQueryString = function(queryControl, query) {
11     queryControl.value = query;
12   };
14   var createDoQueryFunction = function(queryControl, submitControl, query) {
15     return function() {
16       setQueryString(queryControl, query);
17       submitControl.click();
18     };
19   };
21   /**
22    * Decorates the quick search controls
23    *
24    * @param {Array of DOM elements} quickLinkArray The <a> object which
25    *     will be given a link to a quick filter option.
26    * @param {!HTMLInputElement} queryControl The <input> object of
27    *     type=search where user's query is typed.
28    */
29   var decorateQuickQueryControls = function(quickLinkArray, submitControl,
30                                             queryControl) {
31     for (var index = 0; index < allLinks.length; ++index) {
32       var quickQuery = allLinks[index].getAttribute('data-query');
33       var quickQueryFunction = createDoQueryFunction(queryControl,
34           submitControl, quickQuery);
35       allLinks[index].addEventListener('click', quickQueryFunction);
36     }
37   };
39   /**
40    * Runs a search with the given query.
41    *
42    * @param {string} query The regex to do the search with.
43    * @param {function} callback The callback called with the search results;
44    *     not called if doSearch() is called again while the search is running.
45    */
46   var doSearch = function(query, callback) {
47     var searchId = ++currSearchId;
48     try {
49       var regex = new RegExp(query);
50       chrome.sync.getAllNodes(function(node_map) {
51         // Put all nodes into one big list that ignores the type.
52         var nodes = node_map.
53             map(function(x) { return x.nodes; }).
54             reduce(function(a, b) { return a.concat(b); });
56         if (currSearchId != searchId) {
57           return;
58         }
59         callback(nodes.filter(function(elem) {
60           return regex.test(JSON.stringify(elem, null, 2));
61         }), null);
62       });
63     } catch (err) {
64       // Sometimes the provided regex is invalid.  This and other errors will
65       // be caught and handled here.
66       callback([], err);
67     }
68   };
70   /**
71    * Decorates the various search controls.
72    *
73    * @param {!HTMLInputElement} queryControl The <input> object of
74    *     type=search where the user's query is typed.
75    * @param {!HTMLButtonElement} submitControl The <button> object
76    *     where the user can click to submit the query.
77    * @param {!HTMLElement} statusControl The <span> object display the
78    *     search status.
79    * @param {!HTMLElement} listControl The <list> object which holds
80    *     the list of returned results.
81    * @param {!HTMLPreElement} detailsControl The <pre> object which
82    *     holds the details of the selected result.
83    */
84   function decorateSearchControls(queryControl, submitControl, statusControl,
85                                   resultsControl, detailsControl) {
86     var resultsDataModel = new cr.ui.ArrayDataModel([]);
88     var searchFunction = function() {
89       var query = queryControl.value;
90       statusControl.textContent = '';
91       resultsDataModel.splice(0, resultsDataModel.length);
92       if (!query) {
93         return;
94       }
95       statusControl.textContent = 'Searching for ' + query + '...';
96       queryControl.removeAttribute('error');
97       var timer = chrome.sync.makeTimer();
98       doSearch(query, function(nodes, error) {
99         if (error) {
100           statusControl.textContent = 'Error: ' + error;
101           queryControl.setAttribute('error', '');
102         } else {
103           statusControl.textContent =
104             'Found ' + nodes.length + ' nodes in ' +
105             timer.getElapsedSeconds() + 's';
106           queryControl.removeAttribute('error');
108           // TODO(akalin): Write a nicer list display.
109           for (var i = 0; i < nodes.length; ++i) {
110             nodes[i].toString = function() {
111               return this.NON_UNIQUE_NAME;
112             };
113           }
114           resultsDataModel.push.apply(resultsDataModel, nodes);
115           // Workaround for http://crbug.com/83452 .
116           resultsControl.redraw();
117         }
118       });
119     };
121     submitControl.addEventListener('click', searchFunction);
122     // Decorate search box.
123     queryControl.onsearch = searchFunction;
124     queryControl.value = '';
126     // Decorate results list.
127     cr.ui.List.decorate(resultsControl);
128     resultsControl.dataModel = resultsDataModel;
129     resultsControl.selectionModel.addEventListener('change', function(event) {
130       detailsControl.textContent = '';
131       var selected = resultsControl.selectedItem;
132       if (selected) {
133         detailsControl.textContent = JSON.stringify(selected, null, 2);
134       }
135     });
136   }
138   return {
139     decorateSearchControls: decorateSearchControls,
140     decorateQuickQueryControls: decorateQuickQueryControls
141   };