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

Side by Side Diff: chrome/browser/resources/history/history.js

Issue 454223004: Typecheck JS files for chrome://history (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@B_download
Patch Set: fixed issues Created 6 years, 4 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 <include src="../uber/uber_utils.js"> 5 <include src="../uber/uber_utils.js">
6 <include src="history_focus_manager.js"> 6 <include src="history_focus_manager.js">
7 7
8 /////////////////////////////////////////////////////////////////////////////// 8 ///////////////////////////////////////////////////////////////////////////////
9 // Globals: 9 // Globals:
10 /** @const */ var RESULTS_PER_PAGE = 150; 10 /** @const */ var RESULTS_PER_PAGE = 150;
(...skipping 20 matching lines...) Expand all
31 /** @const */ var Command = cr.ui.Command; 31 /** @const */ var Command = cr.ui.Command;
32 /** @const */ var Menu = cr.ui.Menu; 32 /** @const */ var Menu = cr.ui.Menu;
33 /** @const */ var MenuButton = cr.ui.MenuButton; 33 /** @const */ var MenuButton = cr.ui.MenuButton;
34 34
35 /** 35 /**
36 * Enum that shows the filtering behavior for a host or URL to a supervised 36 * Enum that shows the filtering behavior for a host or URL to a supervised
37 * user. Must behave like the FilteringBehavior enum from 37 * user. Must behave like the FilteringBehavior enum from
38 * supervised_user_url_filter.h. 38 * supervised_user_url_filter.h.
39 * @enum {number} 39 * @enum {number}
40 */ 40 */
41 SupervisedUserFilteringBehavior = { 41 var SupervisedUserFilteringBehavior = {
42 ALLOW: 0, 42 ALLOW: 0,
43 WARN: 1, 43 WARN: 1,
44 BLOCK: 2 44 BLOCK: 2
45 }; 45 };
46 46
47 /**
48 * The type of the history result object. The definition is based on
49 * chrome/browser/ui/webui/history_ui.cc:
50 * BrowsingHistoryHandler::HistoryEntry::ToValue()
51 * @typedef {{allTimestamps: Array.<number>,
52 * blockedVisit: (boolean|undefined),
53 * dateRelativeDay: (string|undefined),
54 * dateShort: string,
55 * dateTimeOfDay: (string|undefined),
56 * deviceName: string,
57 * deviceType: string,
58 * domain: string,
59 * hostFilteringBehavior: (number|undefined),
60 * snippet: (string|undefined),
61 * starred: boolean,
62 * time: number,
63 * title: string,
64 * url: string}}
65 */
66 var HistoryEntry;
67
68 /**
69 * The type of the history results info object. The definition is based on
70 * chrome/browser/ui/webui/history_ui.cc:
71 * BrowsingHistoryHandler::QueryComplete()
72 * @typedef {{finished: boolean,
73 * hasSyncedResults: (boolean|undefined),
74 * queryEndTime: string,
75 * queryStartTime: string,
76 * term: string}}
77 */
78 var HistoryQuery;
79
47 MenuButton.createDropDownArrows(); 80 MenuButton.createDropDownArrows();
48 81
49 /** 82 /**
50 * Returns true if the mobile (non-desktop) version is being shown. 83 * Returns true if the mobile (non-desktop) version is being shown.
51 * @return {boolean} true if the mobile version is being shown. 84 * @return {boolean} true if the mobile version is being shown.
52 */ 85 */
53 function isMobileVersion() { 86 function isMobileVersion() {
54 return !document.body.classList.contains('uber-frame'); 87 return !document.body.classList.contains('uber-frame');
55 } 88 }
56 89
57 /** 90 /**
58 * Record an action in UMA. 91 * Record an action in UMA.
59 * @param {string} actionDesc The name of the action to be logged. 92 * @param {string} actionDesc The name of the action to be logged.
60 */ 93 */
61 function recordUmaAction(actionDesc) { 94 function recordUmaAction(actionDesc) {
62 chrome.send('metricsHandler:recordAction', [actionDesc]); 95 chrome.send('metricsHandler:recordAction', [actionDesc]);
63 } 96 }
64 97
65 /** 98 /**
66 * Record a histogram value in UMA. If specified value is larger than the max 99 * Record a histogram value in UMA. If specified value is larger than the max
67 * bucket value, record the value in the largest bucket. 100 * bucket value, record the value in the largest bucket.
68 * @param {string} histogram The name of the histogram to be recorded in. 101 * @param {string} histogram The name of the histogram to be recorded in.
69 * @param {integer} maxBucketValue The max value for the last histogram bucket. 102 * @param {number} maxBucketValue The max value for the last histogram bucket.
70 * @param {integer} value The value to record in the histogram. 103 * @param {number} value The value to record in the histogram.
71 */ 104 */
72 function recordUmaHistogram(histogram, maxBucketValue, value) { 105 function recordUmaHistogram(histogram, maxBucketValue, value) {
73 chrome.send('metricsHandler:recordInHistogram', 106 chrome.send('metricsHandler:recordInHistogram',
74 [histogram, 107 [histogram,
75 ((value > maxBucketValue) ? maxBucketValue : value), 108 ((value > maxBucketValue) ? maxBucketValue : value),
76 maxBucketValue]); 109 maxBucketValue]);
77 } 110 }
78 111
79 /////////////////////////////////////////////////////////////////////////////// 112 ///////////////////////////////////////////////////////////////////////////////
80 // Visit: 113 // Visit:
81 114
82 /** 115 /**
83 * Class to hold all the information about an entry in our model. 116 * Class to hold all the information about an entry in our model.
84 * @param {Object} result An object containing the visit's data. 117 * @param {HistoryEntry} result An object containing the visit's data.
85 * @param {boolean} continued Whether this visit is on the same day as the 118 * @param {boolean} continued Whether this visit is on the same day as the
86 * visit before it. 119 * visit before it.
87 * @param {HistoryModel} model The model object this entry belongs to. 120 * @param {HistoryModel} model The model object this entry belongs to.
88 * @constructor 121 * @constructor
89 */ 122 */
90 function Visit(result, continued, model) { 123 function Visit(result, continued, model) {
91 this.model_ = model; 124 this.model_ = model;
92 this.title_ = result.title; 125 this.title_ = result.title;
93 this.url_ = result.url; 126 this.url_ = result.url;
94 this.domain_ = result.domain; 127 this.domain_ = result.domain;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 checkbox.time = this.date.getTime(); 199 checkbox.time = this.date.getTime();
167 checkbox.addEventListener('click', checkboxClicked); 200 checkbox.addEventListener('click', checkboxClicked);
168 entryBox.appendChild(checkbox); 201 entryBox.appendChild(checkbox);
169 202
170 if (focusless) 203 if (focusless)
171 checkbox.tabIndex = -1; 204 checkbox.tabIndex = -1;
172 205
173 // Clicking anywhere in the entryBox will check/uncheck the checkbox. 206 // Clicking anywhere in the entryBox will check/uncheck the checkbox.
174 entryBox.setAttribute('for', checkbox.id); 207 entryBox.setAttribute('for', checkbox.id);
175 entryBox.addEventListener('mousedown', entryBoxMousedown); 208 entryBox.addEventListener('mousedown', entryBoxMousedown);
176 entryBox.addEventListener('click', entryBoxClick); 209 entryBox.addEventListener('click', /** @type {function(Event)} */(
Dan Beam 2014/08/20 03:48:55 i liked the other cast better, e.g. e = /** @ty
210 entryBoxClick));
177 entryBox.addEventListener('keydown', this.handleKeydown_.bind(this)); 211 entryBox.addEventListener('keydown', this.handleKeydown_.bind(this));
178 } 212 }
179 213
180 // Keep track of the drop down that triggered the menu, so we know 214 // Keep track of the drop down that triggered the menu, so we know
181 // which element to apply the command to. 215 // which element to apply the command to.
182 // TODO(dubroy): Ideally we'd use 'activate', but MenuButton swallows it. 216 // TODO(dubroy): Ideally we'd use 'activate', but MenuButton swallows it.
183 var setActiveVisit = function(e) { 217 var setActiveVisit = function(e) {
184 activeVisit = self; 218 activeVisit = self;
185 var menu = $('action-menu'); 219 var menu = $('action-menu');
186 menu.dataset.devicename = self.deviceName; 220 menu.dataset.devicename = self.deviceName;
(...skipping 10 matching lines...) Expand all
197 bookmarkSection.addEventListener('click', function f(e) { 231 bookmarkSection.addEventListener('click', function f(e) {
198 recordUmaAction('HistoryPage_BookmarkStarClicked'); 232 recordUmaAction('HistoryPage_BookmarkStarClicked');
199 bookmarkSection.classList.remove('starred'); 233 bookmarkSection.classList.remove('starred');
200 chrome.send('removeBookmark', [self.url_]); 234 chrome.send('removeBookmark', [self.url_]);
201 bookmarkSection.removeEventListener('click', f); 235 bookmarkSection.removeEventListener('click', f);
202 e.preventDefault(); 236 e.preventDefault();
203 }); 237 });
204 } 238 }
205 entryBox.appendChild(bookmarkSection); 239 entryBox.appendChild(bookmarkSection);
206 240
207 var visitEntryWrapper = entryBox.appendChild(document.createElement('div')); 241 var visitEntryWrapper = /** @type {HTMLElement} */(
242 entryBox.appendChild(document.createElement('div')));
208 if (addTitleFavicon || this.blockedVisit) 243 if (addTitleFavicon || this.blockedVisit)
209 visitEntryWrapper.classList.add('visit-entry'); 244 visitEntryWrapper.classList.add('visit-entry');
210 if (this.blockedVisit) { 245 if (this.blockedVisit) {
211 visitEntryWrapper.classList.add('blocked-indicator'); 246 visitEntryWrapper.classList.add('blocked-indicator');
212 visitEntryWrapper.appendChild(this.getVisitAttemptDOM_()); 247 visitEntryWrapper.appendChild(this.getVisitAttemptDOM_());
213 } else { 248 } else {
214 var title = visitEntryWrapper.appendChild( 249 var title = visitEntryWrapper.appendChild(
215 this.getTitleDOM_(isSearchResult)); 250 this.getTitleDOM_(isSearchResult));
216 251
217 if (addTitleFavicon) 252 if (addTitleFavicon)
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 /** 327 /**
293 * Remove this visit from the history. 328 * Remove this visit from the history.
294 */ 329 */
295 Visit.prototype.removeFromHistory = function() { 330 Visit.prototype.removeFromHistory = function() {
296 recordUmaAction('HistoryPage_EntryMenuRemoveFromHistory'); 331 recordUmaAction('HistoryPage_EntryMenuRemoveFromHistory');
297 this.model_.removeVisitsFromHistory([this], function() { 332 this.model_.removeVisitsFromHistory([this], function() {
298 this.model_.getView().removeVisit(this); 333 this.model_.getView().removeVisit(this);
299 }.bind(this)); 334 }.bind(this));
300 }; 335 };
301 336
337 // Closure Compiler doesn't support Object.defineProperty().
338 // https://github.com/google/closure-compiler/issues/302
302 Object.defineProperty(Visit.prototype, 'checkBox', { 339 Object.defineProperty(Visit.prototype, 'checkBox', {
303 get: function() { 340 get: /** @this {Visit} */function() {
304 return this.domNode_.querySelector('input[type=checkbox]'); 341 return this.domNode_.querySelector('input[type=checkbox]');
305 }, 342 },
306 }); 343 });
307 344
308 Object.defineProperty(Visit.prototype, 'bookmarkStar', { 345 Object.defineProperty(Visit.prototype, 'bookmarkStar', {
309 get: function() { 346 get: /** @this {Visit} */function() {
310 return this.domNode_.querySelector('.bookmark-section.starred'); 347 return this.domNode_.querySelector('.bookmark-section.starred');
311 }, 348 },
312 }); 349 });
313 350
314 Object.defineProperty(Visit.prototype, 'titleLink', { 351 Object.defineProperty(Visit.prototype, 'titleLink', {
315 get: function() { 352 get: /** @this {Visit} */function() {
316 return this.domNode_.querySelector('.title a'); 353 return this.domNode_.querySelector('.title a');
317 }, 354 },
318 }); 355 });
319 356
320 Object.defineProperty(Visit.prototype, 'dropDown', { 357 Object.defineProperty(Visit.prototype, 'dropDown', {
321 get: function() { 358 get: /** @this {Visit} */function() {
322 return this.domNode_.querySelector('button.drop-down'); 359 return this.domNode_.querySelector('button.drop-down');
323 }, 360 },
324 }); 361 });
325 362
326 // Visit, private: ------------------------------------------------------------ 363 // Visit, private: ------------------------------------------------------------
327 364
328 /** 365 /**
329 * Add child text nodes to a node such that occurrences of the specified text is 366 * Add child text nodes to a node such that occurrences of the specified text is
330 * highlighted. 367 * highlighted.
331 * @param {Node} node The node under which new text nodes will be made as 368 * @param {Node} node The node under which new text nodes will be made as
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 * the data becomes available, the model will call the view back. 590 * the data becomes available, the model will call the view back.
554 * @param {number} page The page we want to view. 591 * @param {number} page The page we want to view.
555 */ 592 */
556 HistoryModel.prototype.requestPage = function(page) { 593 HistoryModel.prototype.requestPage = function(page) {
557 this.requestedPage_ = page; 594 this.requestedPage_ = page;
558 this.updateSearch_(); 595 this.updateSearch_();
559 }; 596 };
560 597
561 /** 598 /**
562 * Receiver for history query. 599 * Receiver for history query.
563 * @param {Object} info An object containing information about the query. 600 * @param {HistoryQuery} info An object containing information about the query.
564 * @param {Array} results A list of results. 601 * @param {Array.<HistoryEntry>} results A list of results.
565 */ 602 */
566 HistoryModel.prototype.addResults = function(info, results) { 603 HistoryModel.prototype.addResults = function(info, results) {
567 // If no requests are in flight then this was an old request so we drop the 604 // If no requests are in flight then this was an old request so we drop the
568 // results. Double check the search term as well. 605 // results. Double check the search term as well.
569 if (!this.inFlight_ || info.term != this.searchText_) 606 if (!this.inFlight_ || info.term != this.searchText_)
570 return; 607 return;
571 608
572 $('loading-spinner').hidden = true; 609 $('loading-spinner').hidden = true;
573 this.inFlight_ = false; 610 this.inFlight_ = false;
574 this.isQueryFinished_ = info.finished; 611 this.isQueryFinished_ = info.finished;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 * @return {boolean} true if the there are more results, otherwise false. 653 * @return {boolean} true if the there are more results, otherwise false.
617 */ 654 */
618 HistoryModel.prototype.hasMoreResults = function() { 655 HistoryModel.prototype.hasMoreResults = function() {
619 return this.haveDataForPage_(this.requestedPage_ + 1) || 656 return this.haveDataForPage_(this.requestedPage_ + 1) ||
620 !this.isQueryFinished_; 657 !this.isQueryFinished_;
621 }; 658 };
622 659
623 /** 660 /**
624 * Removes a list of visits from the history, and calls |callback| when the 661 * Removes a list of visits from the history, and calls |callback| when the
625 * removal has successfully completed. 662 * removal has successfully completed.
626 * @param {Array<Visit>} visits The visits to remove. 663 * @param {Array.<Visit>} visits The visits to remove.
627 * @param {Function} callback The function to call after removal succeeds. 664 * @param {Function} callback The function to call after removal succeeds.
628 */ 665 */
629 HistoryModel.prototype.removeVisitsFromHistory = function(visits, callback) { 666 HistoryModel.prototype.removeVisitsFromHistory = function(visits, callback) {
630 assert(this.deletingHistoryAllowed); 667 assert(this.deletingHistoryAllowed);
631 668
632 var toBeRemoved = []; 669 var toBeRemoved = [];
633 for (var i = 0; i < visits.length; i++) { 670 for (var i = 0; i < visits.length; i++) {
634 toBeRemoved.push({ 671 toBeRemoved.push({
635 url: visits[i].url_, 672 url: visits[i].url_,
636 timestamps: visits[i].allTimestamps 673 timestamps: visits[i].allTimestamps
(...skipping 13 matching lines...) Expand all
650 * Called when visits have been succesfully removed from the history. 687 * Called when visits have been succesfully removed from the history.
651 */ 688 */
652 HistoryModel.prototype.deleteComplete = function() { 689 HistoryModel.prototype.deleteComplete = function() {
653 // Call the callback, with 'this' undefined inside the callback. 690 // Call the callback, with 'this' undefined inside the callback.
654 this.deleteCompleteCallback_.call(); 691 this.deleteCompleteCallback_.call();
655 this.deleteCompleteCallback_ = null; 692 this.deleteCompleteCallback_ = null;
656 }; 693 };
657 694
658 // Getter and setter for HistoryModel.rangeInDays_. 695 // Getter and setter for HistoryModel.rangeInDays_.
659 Object.defineProperty(HistoryModel.prototype, 'rangeInDays', { 696 Object.defineProperty(HistoryModel.prototype, 'rangeInDays', {
660 get: function() { 697 get: /** @this {HistoryModel} */function() {
661 return this.rangeInDays_; 698 return this.rangeInDays_;
662 }, 699 },
663 set: function(range) { 700 set: /** @this {HistoryModel} */function(range) {
664 this.rangeInDays_ = range; 701 this.rangeInDays_ = range;
665 } 702 }
666 }); 703 });
667 704
668 /** 705 /**
669 * Getter and setter for HistoryModel.offset_. The offset moves the current 706 * Getter and setter for HistoryModel.offset_. The offset moves the current
670 * query 'window' |range| days behind. As such for range set to WEEK an offset 707 * query 'window' |range| days behind. As such for range set to WEEK an offset
671 * of 0 refers to the last 7 days, an offset of 1 refers to the 7 day period 708 * of 0 refers to the last 7 days, an offset of 1 refers to the 7 day period
672 * that ended 7 days ago, etc. For MONTH an offset of 0 refers to the current 709 * that ended 7 days ago, etc. For MONTH an offset of 0 refers to the current
673 * calendar month, 1 to the previous one, etc. 710 * calendar month, 1 to the previous one, etc.
674 */ 711 */
675 Object.defineProperty(HistoryModel.prototype, 'offset', { 712 Object.defineProperty(HistoryModel.prototype, 'offset', {
676 get: function() { 713 get: /** @this {HistoryModel} */function() {
677 return this.offset_; 714 return this.offset_;
678 }, 715 },
679 set: function(offset) { 716 set: /** @this {HistoryModel} */function(offset) {
680 this.offset_ = offset; 717 this.offset_ = offset;
681 } 718 }
682 }); 719 });
683 720
684 // Setter for HistoryModel.requestedPage_. 721 // Setter for HistoryModel.requestedPage_.
685 Object.defineProperty(HistoryModel.prototype, 'requestedPage', { 722 Object.defineProperty(HistoryModel.prototype, 'requestedPage', {
686 set: function(page) { 723 set: /** @this {HistoryModel} */function(page) {
687 this.requestedPage_ = page; 724 this.requestedPage_ = page;
688 } 725 }
689 }); 726 });
690 727
691 /** 728 /**
692 * Removes |visit| from this model. 729 * Removes |visit| from this model.
693 * @param {Visit} visit A visit to remove. 730 * @param {Visit} visit A visit to remove.
694 */ 731 */
695 HistoryModel.prototype.removeVisit = function(visit) { 732 HistoryModel.prototype.removeVisit = function(visit) {
696 var index = this.visits_.indexOf(visit); 733 var index = this.visits_.indexOf(visit);
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
814 * Gets whether we are grouped by domain. 851 * Gets whether we are grouped by domain.
815 * @return {boolean} Whether the results are grouped by domain. 852 * @return {boolean} Whether the results are grouped by domain.
816 */ 853 */
817 HistoryModel.prototype.getGroupByDomain = function() { 854 HistoryModel.prototype.getGroupByDomain = function() {
818 return this.groupByDomain_; 855 return this.groupByDomain_;
819 }; 856 };
820 857
821 /////////////////////////////////////////////////////////////////////////////// 858 ///////////////////////////////////////////////////////////////////////////////
822 // HistoryFocusObserver: 859 // HistoryFocusObserver:
823 860
824 /** @implements {cr.ui.FocusRow.Observer} */ 861 /**
862 * @constructor
863 * @implements {cr.ui.FocusRow.Observer}
864 */
825 function HistoryFocusObserver() {} 865 function HistoryFocusObserver() {}
826 866
827 HistoryFocusObserver.prototype = { 867 HistoryFocusObserver.prototype = {
828 /** @override */ 868 /** @override */
829 onActivate: function(row) { 869 onActivate: function(row) {
830 this.getActiveRowElement_(row).classList.add('active'); 870 this.getActiveRowElement_(row).classList.add('active');
831 }, 871 },
832 872
833 /** @override */ 873 /** @override */
834 onDeactivate: function(row) { 874 onDeactivate: function(row) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 recordUmaAction('HistoryPage_NewerHistoryClick'); 930 recordUmaAction('HistoryPage_NewerHistoryClick');
891 self.setPage(self.pageIndex_ - 1); 931 self.setPage(self.pageIndex_ - 1);
892 }); 932 });
893 $('older-button').addEventListener('click', function() { 933 $('older-button').addEventListener('click', function() {
894 recordUmaAction('HistoryPage_OlderHistoryClick'); 934 recordUmaAction('HistoryPage_OlderHistoryClick');
895 self.setPage(self.pageIndex_ + 1); 935 self.setPage(self.pageIndex_ + 1);
896 }); 936 });
897 937
898 var handleRangeChange = function(e) { 938 var handleRangeChange = function(e) {
899 // Update the results and save the last state. 939 // Update the results and save the last state.
900 self.setRangeInDays(parseInt(e.target.value, 10)); 940 var value = parseInt(e.target.value, 10);
941 self.setRangeInDays(/** @type {HistoryModel.Range.<number>} */(value));
901 }; 942 };
902 943
903 // Add handlers for the range options. 944 // Add handlers for the range options.
904 $('timeframe-filter-all').addEventListener('change', handleRangeChange); 945 $('timeframe-filter-all').addEventListener('change', handleRangeChange);
905 $('timeframe-filter-week').addEventListener('change', handleRangeChange); 946 $('timeframe-filter-week').addEventListener('change', handleRangeChange);
906 $('timeframe-filter-month').addEventListener('change', handleRangeChange); 947 $('timeframe-filter-month').addEventListener('change', handleRangeChange);
907 948
908 $('range-previous').addEventListener('click', function(e) { 949 $('range-previous').addEventListener('click', function(e) {
909 if (self.getRangeInDays() == HistoryModel.Range.ALL_TIME) 950 if (self.getRangeInDays() == HistoryModel.Range.ALL_TIME)
910 self.setPage(self.pageIndex_ + 1); 951 self.setPage(self.pageIndex_ + 1);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
988 1029
989 /** 1030 /**
990 * @return {number} The page number being viewed. 1031 * @return {number} The page number being viewed.
991 */ 1032 */
992 HistoryView.prototype.getPage = function() { 1033 HistoryView.prototype.getPage = function() {
993 return this.pageIndex_; 1034 return this.pageIndex_;
994 }; 1035 };
995 1036
996 /** 1037 /**
997 * Set the current range for grouped results. 1038 * Set the current range for grouped results.
998 * @param {string} range The number of days to which the range should be set. 1039 * @param {HistoryModel.Range} range The number of days to which the range
1040 * should be set.
999 */ 1041 */
1000 HistoryView.prototype.setRangeInDays = function(range) { 1042 HistoryView.prototype.setRangeInDays = function(range) {
1001 // Set the range, offset and reset the page. 1043 // Set the range, offset and reset the page.
1002 this.setPageState(this.model_.getSearchText(), 0, range, 0); 1044 this.setPageState(this.model_.getSearchText(), 0, range, 0);
1003 }; 1045 };
1004 1046
1005 /** 1047 /**
1006 * Get the current range in days. 1048 * Get the current range in days.
1007 * @return {number} Current range in days from the model. 1049 * @return {HistoryModel.Range} Current range in days from the model.
1008 */ 1050 */
1009 HistoryView.prototype.getRangeInDays = function() { 1051 HistoryView.prototype.getRangeInDays = function() {
1010 return this.model_.rangeInDays; 1052 return this.model_.rangeInDays;
1011 }; 1053 };
1012 1054
1013 /** 1055 /**
1014 * Set the current offset for grouped results. 1056 * Set the current offset for grouped results.
1015 * @param {number} offset Offset to set. 1057 * @param {number} offset Offset to set.
1016 */ 1058 */
1017 HistoryView.prototype.setOffset = function(offset) { 1059 HistoryView.prototype.setOffset = function(offset) {
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
1355 1397
1356 for (var i = 0; i < domains.length; ++i) { 1398 for (var i = 0; i < domains.length; ++i) {
1357 var domain = domains[i]; 1399 var domain = domains[i];
1358 this.getGroupedVisitsDOM_(results, domain, visitsByDomain[domain]); 1400 this.getGroupedVisitsDOM_(results, domain, visitsByDomain[domain]);
1359 } 1401 }
1360 }; 1402 };
1361 1403
1362 /** 1404 /**
1363 * Adds the results for a month. 1405 * Adds the results for a month.
1364 * @param {Array} visits Visits returned by the query. 1406 * @param {Array} visits Visits returned by the query.
1365 * @param {Element} parentElement Element to which to add the results to. 1407 * @param {Node} parentNode Node to which to add the results to.
1366 * @private 1408 * @private
1367 */ 1409 */
1368 HistoryView.prototype.addMonthResults_ = function(visits, parentElement) { 1410 HistoryView.prototype.addMonthResults_ = function(visits, parentNode) {
1369 if (visits.length == 0) 1411 if (visits.length == 0)
1370 return; 1412 return;
1371 1413
1372 var monthResults = parentElement.appendChild( 1414 var monthResults = /** @type {HTMLOListElement} */(parentNode.appendChild(
1373 createElementWithClassName('ol', 'month-results')); 1415 createElementWithClassName('ol', 'month-results')));
1374 // Don't add checkboxes if entries can not be edited. 1416 // Don't add checkboxes if entries can not be edited.
1375 if (!this.model_.editingEntriesAllowed) 1417 if (!this.model_.editingEntriesAllowed)
1376 monthResults.classList.add('no-checkboxes'); 1418 monthResults.classList.add('no-checkboxes');
1377 1419
1378 this.groupVisitsByDomain_(visits, monthResults); 1420 this.groupVisitsByDomain_(visits, monthResults);
1379 }; 1421 };
1380 1422
1381 /** 1423 /**
1382 * Adds the results for a certain day. This includes a title with the day of 1424 * Adds the results for a certain day. This includes a title with the day of
1383 * the results and the results themselves, grouped or not. 1425 * the results and the results themselves, grouped or not.
1384 * @param {Array} visits Visits returned by the query. 1426 * @param {Array} visits Visits returned by the query.
1385 * @param {Element} parentElement Element to which to add the results to. 1427 * @param {Node} parentNode Node to which to add the results to.
1386 * @private 1428 * @private
1387 */ 1429 */
1388 HistoryView.prototype.addDayResults_ = function(visits, parentElement) { 1430 HistoryView.prototype.addDayResults_ = function(visits, parentNode) {
1389 if (visits.length == 0) 1431 if (visits.length == 0)
1390 return; 1432 return;
1391 1433
1392 var firstVisit = visits[0]; 1434 var firstVisit = visits[0];
1393 var day = parentElement.appendChild(createElementWithClassName('h3', 'day')); 1435 var day = parentNode.appendChild(createElementWithClassName('h3', 'day'));
1394 day.appendChild(document.createTextNode(firstVisit.dateRelativeDay)); 1436 day.appendChild(document.createTextNode(firstVisit.dateRelativeDay));
1395 if (firstVisit.continued) { 1437 if (firstVisit.continued) {
1396 day.appendChild(document.createTextNode(' ' + 1438 day.appendChild(document.createTextNode(' ' +
1397 loadTimeData.getString('cont'))); 1439 loadTimeData.getString('cont')));
1398 } 1440 }
1399 var dayResults = parentElement.appendChild( 1441 var dayResults = /** @type {HTMLElement} */(parentNode.appendChild(
1400 createElementWithClassName('ol', 'day-results')); 1442 createElementWithClassName('ol', 'day-results')));
1401 1443
1402 // Don't add checkboxes if entries can not be edited. 1444 // Don't add checkboxes if entries can not be edited.
1403 if (!this.model_.editingEntriesAllowed) 1445 if (!this.model_.editingEntriesAllowed)
1404 dayResults.classList.add('no-checkboxes'); 1446 dayResults.classList.add('no-checkboxes');
1405 1447
1406 if (this.model_.getGroupByDomain()) { 1448 if (this.model_.getGroupByDomain()) {
1407 this.groupVisitsByDomain_(visits, dayResults); 1449 this.groupVisitsByDomain_(visits, dayResults);
1408 } else { 1450 } else {
1409 var lastTime; 1451 var lastTime;
1410 1452
1411 for (var i = 0, visit; visit = visits[i]; i++) { 1453 for (var i = 0, visit; visit = visits[i]; i++) {
1412 // If enough time has passed between visits, indicate a gap in browsing. 1454 // If enough time has passed between visits, indicate a gap in browsing.
1413 var thisTime = visit.date.getTime(); 1455 var thisTime = visit.date.getTime();
1414 if (lastTime && lastTime - thisTime > BROWSING_GAP_TIME) 1456 if (lastTime && lastTime - thisTime > BROWSING_GAP_TIME)
1415 dayResults.appendChild(createElementWithClassName('li', 'gap')); 1457 dayResults.appendChild(createElementWithClassName('li', 'gap'));
1416 1458
1417 // Insert the visit into the DOM. 1459 // Insert the visit into the DOM.
1418 dayResults.appendChild(visit.getResultDOM({ addTitleFavicon: true })); 1460 dayResults.appendChild(visit.getResultDOM({ addTitleFavicon: true }));
1419 this.setVisitRendered_(visit); 1461 this.setVisitRendered_(visit);
1420 1462
1421 lastTime = thisTime; 1463 lastTime = thisTime;
1422 } 1464 }
1423 } 1465 }
1424 }; 1466 };
1425 1467
1426 /** 1468 /**
1427 * Adds the text that shows the current interval, used for week and month 1469 * Adds the text that shows the current interval, used for week and month
1428 * results. 1470 * results.
1429 * @param {Element} resultsFragment The element to which the interval will be 1471 * @param {Node} resultsFragment The element to which the interval will be
1430 * added to. 1472 * added to.
1431 * @private 1473 * @private
1432 */ 1474 */
1433 HistoryView.prototype.addTimeframeInterval_ = function(resultsFragment) { 1475 HistoryView.prototype.addTimeframeInterval_ = function(resultsFragment) {
1434 if (this.getRangeInDays() == HistoryModel.Range.ALL_TIME) 1476 if (this.getRangeInDays() == HistoryModel.Range.ALL_TIME)
1435 return; 1477 return;
1436 1478
1437 // If this is a time range result add some text that shows what is the 1479 // If this is a time range result add some text that shows what is the
1438 // time range for the results the user is viewing. 1480 // time range for the results the user is viewing.
1439 var timeFrame = resultsFragment.appendChild( 1481 var timeFrame = resultsFragment.appendChild(
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1519 // Go through all of the visits and process them in chunks of one day. 1561 // Go through all of the visits and process them in chunks of one day.
1520 while (dayEnd < results.length) { 1562 while (dayEnd < results.length) {
1521 // Skip over the ones that are already rendered. 1563 // Skip over the ones that are already rendered.
1522 while (dayStart < results.length && results[dayStart].isRendered) 1564 while (dayStart < results.length && results[dayStart].isRendered)
1523 ++dayStart; 1565 ++dayStart;
1524 var dayEnd = dayStart + 1; 1566 var dayEnd = dayStart + 1;
1525 while (dayEnd < results.length && results[dayEnd].continued) 1567 while (dayEnd < results.length && results[dayEnd].continued)
1526 ++dayEnd; 1568 ++dayEnd;
1527 1569
1528 this.addDayResults_( 1570 this.addDayResults_(
1529 results.slice(dayStart, dayEnd), resultsFragment, groupByDomain); 1571 results.slice(dayStart, dayEnd), resultsFragment);
1530 } 1572 }
1531 } 1573 }
1532 1574
1533 // Add all the days and their visits to the page. 1575 // Add all the days and their visits to the page.
1534 this.resultDiv_.appendChild(resultsFragment); 1576 this.resultDiv_.appendChild(resultsFragment);
1535 } 1577 }
1536 // After the results have been added to the DOM, determine the size of the 1578 // After the results have been added to the DOM, determine the size of the
1537 // time column. 1579 // time column.
1538 this.setTimeColumnWidth_(this.resultDiv_); 1580 this.setTimeColumnWidth_();
1539 }; 1581 };
1540 1582
1541 var focusGridRowSelector = [ 1583 var focusGridRowSelector = [
1542 '.day-results > .entry:not(.fade-out)', 1584 '.day-results > .entry:not(.fade-out)',
1543 '.expand .grouped .entry:not(.fade-out)', 1585 '.expand .grouped .entry:not(.fade-out)',
1544 '.site-domain-wrapper' 1586 '.site-domain-wrapper'
1545 ].join(', '); 1587 ].join(', ');
1546 1588
1547 var focusGridColumnSelector = [ 1589 var focusGridColumnSelector = [
1548 '.entry-box input', 1590 '.entry-box input',
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1622 var styleEl = $('timeColumnStyle'); 1664 var styleEl = $('timeColumnStyle');
1623 if (!styleEl) { 1665 if (!styleEl) {
1624 styleEl = document.head.appendChild(document.createElement('style')); 1666 styleEl = document.head.appendChild(document.createElement('style'));
1625 styleEl.id = 'timeColumnStyle'; 1667 styleEl.id = 'timeColumnStyle';
1626 } 1668 }
1627 styleEl.textContent = '.entry .time { min-width: ' + maxWidth + 'px; }'; 1669 styleEl.textContent = '.entry .time { min-width: ' + maxWidth + 'px; }';
1628 }; 1670 };
1629 1671
1630 /** 1672 /**
1631 * Toggles an element in the grouped history. 1673 * Toggles an element in the grouped history.
1632 * @param {Element} e The element which was clicked on. 1674 * @param {Event} e The event with element |e.target| which was clicked on.
1633 * @private 1675 * @private
1634 */ 1676 */
1635 HistoryView.prototype.toggleGroupedVisits_ = function(e) { 1677 HistoryView.prototype.toggleGroupedVisits_ = function(e) {
1636 var entry = findAncestorByClass(e.target, 'site-entry'); 1678 var entry = findAncestorByClass(/** @type {Element} */(e.target),
1679 'site-entry');
1637 var innerResultList = entry.querySelector('.site-results'); 1680 var innerResultList = entry.querySelector('.site-results');
1638 1681
1639 if (entry.classList.contains('expand')) { 1682 if (entry.classList.contains('expand')) {
1640 innerResultList.style.height = 0; 1683 innerResultList.style.height = 0;
1641 } else { 1684 } else {
1642 innerResultList.style.height = 'auto'; 1685 innerResultList.style.height = 'auto';
1643 // -webkit-transition does not work on height:auto elements so first set 1686 // -webkit-transition does not work on height:auto elements so first set
1644 // the height to auto so that it is computed and then set it to the 1687 // the height to auto so that it is computed and then set it to the
1645 // computed value in pixels so the transition works properly. 1688 // computed value in pixels so the transition works properly.
1646 var height = innerResultList.clientHeight; 1689 var height = innerResultList.clientHeight;
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
1779 var searchField = $('search-field'); 1822 var searchField = $('search-field');
1780 1823
1781 historyModel = new HistoryModel(); 1824 historyModel = new HistoryModel();
1782 historyView = new HistoryView(historyModel); 1825 historyView = new HistoryView(historyModel);
1783 pageState = new PageState(historyModel, historyView); 1826 pageState = new PageState(historyModel, historyView);
1784 1827
1785 // Create default view. 1828 // Create default view.
1786 var hashData = pageState.getHashData(); 1829 var hashData = pageState.getHashData();
1787 var grouped = (hashData.grouped == 'true') || historyModel.getGroupByDomain(); 1830 var grouped = (hashData.grouped == 'true') || historyModel.getGroupByDomain();
1788 var page = parseInt(hashData.page, 10) || historyView.getPage(); 1831 var page = parseInt(hashData.page, 10) || historyView.getPage();
1789 var range = parseInt(hashData.range, 10) || historyView.getRangeInDays(); 1832 var range = /** @type {HistoryModel.Range} */(parseInt(hashData.range, 10)) ||
1833 historyView.getRangeInDays();
1790 var offset = parseInt(hashData.offset, 10) || historyView.getOffset(); 1834 var offset = parseInt(hashData.offset, 10) || historyView.getOffset();
1791 historyView.setPageState(hashData.q, page, range, offset); 1835 historyView.setPageState(hashData.q, page, range, offset);
1792 1836
1793 if ($('overlay')) { 1837 if ($('overlay')) {
1794 cr.ui.overlay.setupOverlay($('overlay')); 1838 cr.ui.overlay.setupOverlay($('overlay'));
1795 cr.ui.overlay.globalInitialization(); 1839 cr.ui.overlay.globalInitialization();
1796 } 1840 }
1797 HistoryFocusManager.getInstance().initialize(); 1841 HistoryFocusManager.getInstance().initialize();
1798 1842
1799 var doSearch = function(e) { 1843 var doSearch = function(e) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1853 // visibility, otherwise the button will flash on the screen before the 1897 // visibility, otherwise the button will flash on the screen before the
1854 // keyboard animates away. 1898 // keyboard animates away.
1855 searchField.addEventListener('blur', function() { 1899 searchField.addEventListener('blur', function() {
1856 setTimeout(historyView.updateClearBrowsingDataButton_, 250); 1900 setTimeout(historyView.updateClearBrowsingDataButton_, 250);
1857 }); 1901 });
1858 1902
1859 // Move the button to the bottom of the page. 1903 // Move the button to the bottom of the page.
1860 $('history-page').appendChild($('clear-browsing-data')); 1904 $('history-page').appendChild($('clear-browsing-data'));
1861 } else { 1905 } else {
1862 window.addEventListener('message', function(e) { 1906 window.addEventListener('message', function(e) {
1907 e = /** @type {!MessageEvent.<!{method: string}>} */(e);
1863 if (e.data.method == 'frameSelected') 1908 if (e.data.method == 'frameSelected')
1864 searchField.focus(); 1909 searchField.focus();
1865 }); 1910 });
1866 searchField.focus(); 1911 searchField.focus();
1867 } 1912 }
1868 1913
1869 <if expr="is_ios"> 1914 <if expr="is_ios">
1870 function checkKeyboardVisibility() { 1915 function checkKeyboardVisibility() {
1871 // Figure out the real height based on the orientation, becauase 1916 // Figure out the real height based on the orientation, becauase
1872 // screen.width and screen.height don't update after rotation. 1917 // screen.width and screen.height don't update after rotation.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1926 */ 1971 */
1927 function hideConfirmationOverlay() { 1972 function hideConfirmationOverlay() {
1928 $('alertOverlay').classList.remove('showing'); 1973 $('alertOverlay').classList.remove('showing');
1929 $('overlay').hidden = true; 1974 $('overlay').hidden = true;
1930 uber.invokeMethodOnParent('stopInterceptingEvents'); 1975 uber.invokeMethodOnParent('stopInterceptingEvents');
1931 } 1976 }
1932 1977
1933 /** 1978 /**
1934 * Shows the confirmation alert for history deletions and permits browser tests 1979 * Shows the confirmation alert for history deletions and permits browser tests
1935 * to override the dialog. 1980 * to override the dialog.
1936 * @param {function=} okCallback A function to be called when the user presses 1981 * @param {function()=} okCallback A function to be called when the user presses
1937 * the ok button. 1982 * the ok button.
1938 * @param {function=} cancelCallback A function to be called when the user 1983 * @param {function()=} cancelCallback A function to be called when the user
1939 * presses the cancel button. 1984 * presses the cancel button.
1940 */ 1985 */
1941 function confirmDeletion(okCallback, cancelCallback) { 1986 function confirmDeletion(okCallback, cancelCallback) {
1942 alertOverlay.setValues( 1987 alertOverlay.setValues(
1943 loadTimeData.getString('removeSelected'), 1988 loadTimeData.getString('removeSelected'),
1944 loadTimeData.getString('deleteWarning'), 1989 loadTimeData.getString('deleteWarning'),
1945 loadTimeData.getString('cancel'), 1990 loadTimeData.getString('cancel'),
1946 loadTimeData.getString('deleteConfirm'), 1991 loadTimeData.getString('deleteConfirm'),
1947 cancelCallback, 1992 cancelCallback,
1948 okCallback); 1993 okCallback);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
2014 confirmDeletion(onConfirmRemove, onCancelRemove); 2059 confirmDeletion(onConfirmRemove, onCancelRemove);
2015 $('overlay').addEventListener('cancelOverlay', onCancelRemove); 2060 $('overlay').addEventListener('cancelOverlay', onCancelRemove);
2016 } 2061 }
2017 } 2062 }
2018 2063
2019 /** 2064 /**
2020 * Handler for the 'click' event on a checkbox. 2065 * Handler for the 'click' event on a checkbox.
2021 * @param {Event} e The click event. 2066 * @param {Event} e The click event.
2022 */ 2067 */
2023 function checkboxClicked(e) { 2068 function checkboxClicked(e) {
2024 handleCheckboxStateChange(e.currentTarget, e.shiftKey); 2069 handleCheckboxStateChange(/** @type {!HTMLInputElement} */(e.currentTarget),
2070 e.shiftKey);
2025 } 2071 }
2026 2072
2027 /** 2073 /**
2028 * Post-process of checkbox state change. This handles range selection and 2074 * Post-process of checkbox state change. This handles range selection and
2029 * updates internal state. 2075 * updates internal state.
2030 * @param {!HTMLInputElement} checkbox Clicked checkbox. 2076 * @param {!HTMLInputElement} checkbox Clicked checkbox.
2031 * @param {boolean} shiftKey true if shift key is pressed. 2077 * @param {boolean} shiftKey true if shift key is pressed.
2032 */ 2078 */
2033 function handleCheckboxStateChange(checkbox, shiftKey) { 2079 function handleCheckboxStateChange(checkbox, shiftKey) {
2034 updateParentCheckbox(checkbox); 2080 updateParentCheckbox(checkbox);
2035 var id = Number(checkbox.id.slice('checkbox-'.length)); 2081 var id = Number(checkbox.id.slice('checkbox-'.length));
2036 // Handle multi-select if shift was pressed. 2082 // Handle multi-select if shift was pressed.
2037 if (shiftKey && (selectionAnchor != -1)) { 2083 if (shiftKey && (selectionAnchor != -1)) {
2038 var checked = checkbox.checked; 2084 var checked = checkbox.checked;
2039 // Set all checkboxes from the anchor up to the clicked checkbox to the 2085 // Set all checkboxes from the anchor up to the clicked checkbox to the
2040 // state of the clicked one. 2086 // state of the clicked one.
2041 var begin = Math.min(id, selectionAnchor); 2087 var begin = Math.min(id, selectionAnchor);
2042 var end = Math.max(id, selectionAnchor); 2088 var end = Math.max(id, selectionAnchor);
2043 for (var i = begin; i <= end; i++) { 2089 for (var i = begin; i <= end; i++) {
2044 var checkbox = document.querySelector('#checkbox-' + i); 2090 var ithCheckbox = document.querySelector('#checkbox-' + i);
2045 if (checkbox) { 2091 if (ithCheckbox) {
2046 checkbox.checked = checked; 2092 ithCheckbox.checked = checked;
2047 updateParentCheckbox(checkbox); 2093 updateParentCheckbox(ithCheckbox);
2048 } 2094 }
2049 } 2095 }
2050 } 2096 }
2051 selectionAnchor = id; 2097 selectionAnchor = id;
2052 2098
2053 historyView.updateSelectionEditButtons(); 2099 historyView.updateSelectionEditButtons();
2054 } 2100 }
2055 2101
2056 /** 2102 /**
2057 * Handler for the 'click' event on a domain checkbox. Checkes or unchecks the 2103 * Handler for the 'click' event on a domain checkbox. Checkes or unchecks the
2058 * checkboxes of the visits to this domain in the respective group. 2104 * checkboxes of the visits to this domain in the respective group.
2059 * @param {Event} e The click event. 2105 * @param {Event} e The click event.
2060 */ 2106 */
2061 function domainCheckboxClicked(e) { 2107 function domainCheckboxClicked(e) {
2062 var siteEntry = findAncestorByClass(e.currentTarget, 'site-entry'); 2108 var siteEntry = findAncestorByClass(/** @type {Element} */(e.currentTarget),
2109 'site-entry');
2063 var checkboxes = 2110 var checkboxes =
2064 siteEntry.querySelectorAll('.site-results input[type=checkbox]'); 2111 siteEntry.querySelectorAll('.site-results input[type=checkbox]');
2065 for (var i = 0; i < checkboxes.length; i++) 2112 for (var i = 0; i < checkboxes.length; i++)
2066 checkboxes[i].checked = e.currentTarget.checked; 2113 checkboxes[i].checked = e.currentTarget.checked;
2067 historyView.updateSelectionEditButtons(); 2114 historyView.updateSelectionEditButtons();
2068 // Stop propagation as clicking the checkbox would otherwise trigger the 2115 // Stop propagation as clicking the checkbox would otherwise trigger the
2069 // group to collapse/expand. 2116 // group to collapse/expand.
2070 e.stopPropagation(); 2117 e.stopPropagation();
2071 } 2118 }
2072 2119
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
2166 updateHostStatus(filterStatusDiv, filteringBehavior); 2213 updateHostStatus(filterStatusDiv, filteringBehavior);
2167 return filterStatusDiv; 2214 return filterStatusDiv;
2168 } 2215 }
2169 2216
2170 2217
2171 /////////////////////////////////////////////////////////////////////////////// 2218 ///////////////////////////////////////////////////////////////////////////////
2172 // Chrome callbacks: 2219 // Chrome callbacks:
2173 2220
2174 /** 2221 /**
2175 * Our history system calls this function with results from searches. 2222 * Our history system calls this function with results from searches.
2176 * @param {Object} info An object containing information about the query. 2223 * @param {HistoryQuery} info An object containing information about the query.
2177 * @param {Array} results A list of results. 2224 * @param {Array.<HistoryEntry>} results A list of results.
2178 */ 2225 */
2179 function historyResult(info, results) { 2226 function historyResult(info, results) {
2180 historyModel.addResults(info, results); 2227 historyModel.addResults(info, results);
2181 } 2228 }
2182 2229
2183 /** 2230 /**
2184 * Called by the history backend when history removal is successful. 2231 * Called by the history backend when history removal is successful.
2185 */ 2232 */
2186 function deleteComplete() { 2233 function deleteComplete() {
2187 historyModel.deleteComplete(); 2234 historyModel.deleteComplete();
(...skipping 17 matching lines...) Expand all
2205 historyView.reload(); 2252 historyView.reload();
2206 } 2253 }
2207 2254
2208 // Add handlers to HTML elements. 2255 // Add handlers to HTML elements.
2209 document.addEventListener('DOMContentLoaded', load); 2256 document.addEventListener('DOMContentLoaded', load);
2210 2257
2211 // This event lets us enable and disable menu items before the menu is shown. 2258 // This event lets us enable and disable menu items before the menu is shown.
2212 document.addEventListener('canExecute', function(e) { 2259 document.addEventListener('canExecute', function(e) {
2213 e.canExecute = true; 2260 e.canExecute = true;
2214 }); 2261 });
OLDNEW
« no previous file with comments | « chrome/browser/resources/history/compiled_resources.gyp ('k') | chrome/browser/resources/history/history_focus_manager.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698