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

Side by Side Diff: chrome/browser/resources/md_extensions/manager.js

Issue 2811993004: [MD Extensions] Add support for URL navigation (Closed)
Patch Set: Michael's Created 3 years, 7 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 /**
6 * The different pages that can be shown at a time.
7 * Note: This must remain in sync with the order in manager.html!
8 * @enum {string}
9 */
10 var Page = {
11 ITEM_LIST: '0',
12 DETAIL_VIEW: '1',
13 KEYBOARD_SHORTCUTS: '2',
14 ERROR_PAGE: '3',
15 };
16
17 cr.define('extensions', function() { 5 cr.define('extensions', function() {
18 'use strict'; 6 'use strict';
19 7
20 /** 8 /**
21 * Compares two extensions to determine which should come first in the list. 9 * Compares two extensions to determine which should come first in the list.
22 * @param {chrome.developerPrivate.ExtensionInfo} a 10 * @param {chrome.developerPrivate.ExtensionInfo} a
23 * @param {chrome.developerPrivate.ExtensionInfo} b 11 * @param {chrome.developerPrivate.ExtensionInfo} b
24 * @return {number} 12 * @return {number}
25 */ 13 */
26 var compareExtensions = function(a, b) { 14 var compareExtensions = function(a, b) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 */ 64 */
77 errorPageItem_: Object, 65 errorPageItem_: Object,
78 66
79 /** 67 /**
80 * The item currently displayed in the details view subpage. See also 68 * The item currently displayed in the details view subpage. See also
81 * errorPageItem_. 69 * errorPageItem_.
82 * @private {!chrome.developerPrivate.ExtensionInfo|undefined} 70 * @private {!chrome.developerPrivate.ExtensionInfo|undefined}
83 */ 71 */
84 detailViewItem_: Object, 72 detailViewItem_: Object,
85 73
74 /**
75 * The helper object to maintain page state.
76 * @private {!extensions.NavigationHelper}
77 */
78 navigationHelper_: Object,
79
80 /**
81 * The current page being shown.
82 * @private {!PageState}
83 */
84 currentPage_: Object,
85
86 /** @type {!Array<!chrome.developerPrivate.ExtensionInfo>} */ 86 /** @type {!Array<!chrome.developerPrivate.ExtensionInfo>} */
87 extensions: { 87 extensions: {
88 type: Array, 88 type: Array,
89 value: function() { return []; }, 89 value: function() { return []; },
90 }, 90 },
91 91
92 /** @type {!Array<!chrome.developerPrivate.ExtensionInfo>} */ 92 /** @type {!Array<!chrome.developerPrivate.ExtensionInfo>} */
93 apps: { 93 apps: {
94 type: Array, 94 type: Array,
95 value: function() { return []; }, 95 value: function() { return []; },
(...skipping 11 matching lines...) Expand all
107 107
108 ready: function() { 108 ready: function() {
109 /** @type {extensions.Sidebar} */ 109 /** @type {extensions.Sidebar} */
110 this.sidebar = 110 this.sidebar =
111 /** @type {extensions.Sidebar} */(this.$$('extensions-sidebar')); 111 /** @type {extensions.Sidebar} */(this.$$('extensions-sidebar'));
112 this.toolbar = 112 this.toolbar =
113 /** @type {extensions.Toolbar} */(this.$$('extensions-toolbar')); 113 /** @type {extensions.Toolbar} */(this.$$('extensions-toolbar'));
114 this.listHelper_ = new ListHelper(this); 114 this.listHelper_ = new ListHelper(this);
115 this.sidebar.setListDelegate(this.listHelper_); 115 this.sidebar.setListDelegate(this.listHelper_);
116 this.readyPromiseResolver.resolve(); 116 this.readyPromiseResolver.resolve();
117 this.currentPage_ = {page: Page.LIST};
118 this.navigationHelper_ =
119 new extensions.NavigationHelper(function(newPage) {
120 this.changePage(newPage, true);
121 }.bind(this));
122 this.optionsDialog.addEventListener('close', function() {
123 // We update the page when the options dialog closes, but only if we're
124 // still on the details page. We could be on a different page if the
125 // user hit back while the options dialog was visible; in that case, the
126 // new page is already correct.
127 if (this.currentPage_.page == Page.DETAILS) {
128 // This will update the currentPage_ and the NavigationHelper; since
129 // the active page is already the details page, no main page
130 // transition occurs.
131 this.changePage({page: Page.DETAILS, id: this.currentPage_.id});
132 }
133 }.bind(this));
117 }, 134 },
118 135
119 get keyboardShortcuts() { 136 get keyboardShortcuts() {
120 return this.$['keyboard-shortcuts']; 137 return this.$['keyboard-shortcuts'];
121 }, 138 },
122 139
123 get packDialog() { 140 get packDialog() {
124 return this.$['pack-dialog']; 141 return this.$['pack-dialog'];
125 }, 142 },
126 143
127 get loadError() { 144 get loadError() {
128 return this.$['load-error']; 145 return this.$['load-error'];
129 }, 146 },
130 147
131 get optionsDialog() { 148 get optionsDialog() {
132 return this.$['options-dialog']; 149 return this.$['options-dialog'];
133 }, 150 },
134 151
135 get errorPage() { 152 get errorPage() {
136 return this.$['error-page']; 153 return this.$['error-page'];
137 }, 154 },
138 155
139 /** 156 /**
140 * Shows the details view for a given item. 157 * Shows the details view for a given item.
141 * @param {!chrome.developerPrivate.ExtensionInfo} data 158 * @param {!chrome.developerPrivate.ExtensionInfo} data
142 */ 159 */
143 showItemDetails: function(data) { 160 showItemDetails: function(data) {
144 this.$['items-list'].willShowItemSubpage(data.id); 161 this.changePage({page: Page.DETAILS, id: data.id});
145 this.detailViewItem_ = data;
146 this.changePage(Page.DETAIL_VIEW);
147 }, 162 },
148 163
149 /** 164 /**
165 * Initializes the page to reflect what's specified in the url so that if
166 * the user visits chrome://extensions/?id=..., we land on the proper page.
167 */
168 initPage: function() {
169 this.changePage(this.navigationHelper_.getCurrentPage(), true);
170 },
171
172 /**
150 * @param {!CustomEvent} event 173 * @param {!CustomEvent} event
151 * @private 174 * @private
152 */ 175 */
153 onFilterChanged_: function(event) { 176 onFilterChanged_: function(event) {
154 this.filter = /** @type {string} */ (event.detail); 177 this.filter = /** @type {string} */ (event.detail);
155 }, 178 },
156 179
180 /** @private */
157 onMenuButtonTap_: function() { 181 onMenuButtonTap_: function() {
158 this.$.drawer.toggle(); 182 this.$.drawer.toggle();
159 }, 183 },
160 184
161 /** 185 /**
162 * @param {chrome.developerPrivate.ExtensionType} type The type of item. 186 * @param {chrome.developerPrivate.ExtensionType} type The type of item.
163 * @return {string} The ID of the list that the item belongs in. 187 * @return {string} The ID of the list that the item belongs in.
164 * @private 188 * @private
165 */ 189 */
166 getListId_: function(type) { 190 getListId_: function(type) {
(...skipping 24 matching lines...) Expand all
191 * @return {number} The index of the item in the list, or -1 if not found. 215 * @return {number} The index of the item in the list, or -1 if not found.
192 * @private 216 * @private
193 */ 217 */
194 getIndexInList_: function(listId, itemId) { 218 getIndexInList_: function(listId, itemId) {
195 return this[listId].findIndex(function(item) { 219 return this[listId].findIndex(function(item) {
196 return item.id == itemId; 220 return item.id == itemId;
197 }); 221 });
198 }, 222 },
199 223
200 /** 224 /**
225 * @return {?chrome.developerPrivate.ExtensionInfo}
226 * @private
227 */
228 getData_: function(id) {
229 return this.extensions[this.getIndexInList_('extensions', id)] ||
230 this.apps[this.getIndexInList_('apps', id)];
231 },
232
233 /**
201 * @return {boolean} Whether the list should be visible. 234 * @return {boolean} Whether the list should be visible.
202 * @private 235 * @private
203 */ 236 */
204 computeListHidden_: function() { 237 computeListHidden_: function() {
205 return this.$['items-list'].items.length == 0; 238 return this.$['items-list'].items.length == 0;
206 }, 239 },
207 240
208 /** 241 /**
209 * Creates and adds a new extensions-item element to the list, inserting it 242 * Creates and adds a new extensions-item element to the list, inserting it
210 * into its sorted position in the relevant section. 243 * into its sorted position in the relevant section.
(...skipping 22 matching lines...) Expand all
233 // We should never try and update a non-existent item. 266 // We should never try and update a non-existent item.
234 assert(index >= 0); 267 assert(index >= 0);
235 this.set([listId, index], item); 268 this.set([listId, index], item);
236 269
237 // Update the subpage if it is open and displaying the item. If it's not 270 // Update the subpage if it is open and displaying the item. If it's not
238 // open, we don't update the data even if it's displaying that item. We'll 271 // open, we don't update the data even if it's displaying that item. We'll
239 // set the item correctly before opening the page. It's a little weird 272 // set the item correctly before opening the page. It's a little weird
240 // that the DOM will have stale data, but there's no point in causing the 273 // that the DOM will have stale data, but there's no point in causing the
241 // extra work. 274 // extra work.
242 if (this.detailViewItem_ && this.detailViewItem_.id == item.id && 275 if (this.detailViewItem_ && this.detailViewItem_.id == item.id &&
243 this.$.pages.selected == Page.DETAIL_VIEW) { 276 this.$.pages.selected == Page.DETAILS) {
244 this.detailViewItem_ = item; 277 this.detailViewItem_ = item;
245 } else if (this.errorPageItem_ && this.errorPageItem_.id == item.id && 278 } else if (this.errorPageItem_ && this.errorPageItem_.id == item.id &&
246 this.$.pages.selected == Page.ERROR_PAGE) { 279 this.$.pages.selected == Page.ERRORS) {
247 this.errorPageItem_ = item; 280 this.errorPageItem_ = item;
248 } 281 }
249 }, 282 },
250 283
251 /** 284 /**
252 * @param {!chrome.developerPrivate.ExtensionInfo} item The data for the 285 * @param {!chrome.developerPrivate.ExtensionInfo} item The data for the
253 * item to remove. 286 * item to remove.
254 */ 287 */
255 removeItem: function(item) { 288 removeItem: function(item) {
256 var listId = this.getListId_(item.type); 289 var listId = this.getListId_(item.type);
257 var index = this.getIndexInList_(listId, item.id); 290 var index = this.getIndexInList_(listId, item.id);
258 // We should never try and remove a non-existent item. 291 // We should never try and remove a non-existent item.
259 assert(index >= 0); 292 assert(index >= 0);
260 this.splice(listId, index, 1); 293 this.splice(listId, index, 1);
261 }, 294 },
262 295
263 /** 296 /**
264 * @param {Page} page 297 * @param {Page} page
265 * @return {!(extensions.KeyboardShortcuts | 298 * @return {!(extensions.KeyboardShortcuts |
266 * extensions.DetailView | 299 * extensions.DetailView |
267 * extensions.ItemList)} 300 * extensions.ItemList)}
268 * @private 301 * @private
269 */ 302 */
270 getPage_: function(page) { 303 getPage_: function(page) {
271 switch (page) { 304 switch (page) {
272 case Page.ITEM_LIST: 305 case Page.LIST:
273 return this.$['items-list']; 306 return this.$['items-list'];
274 case Page.DETAIL_VIEW: 307 case Page.DETAILS:
275 return this.$['details-view']; 308 return this.$['details-view'];
276 case Page.KEYBOARD_SHORTCUTS: 309 case Page.SHORTCUTS:
277 return this.$['keyboard-shortcuts']; 310 return this.$['keyboard-shortcuts'];
278 case Page.ERROR_PAGE: 311 case Page.ERRORS:
279 return this.$['error-page']; 312 return this.$['error-page'];
280 } 313 }
281 assertNotReached(); 314 assertNotReached();
282 }, 315 },
283 316
284 /** 317 /**
285 * Changes the active page selection. 318 * Changes the active page selection.
286 * @param {Page} toPage 319 * @param {PageState} newPage
320 * @param {boolean=} isSilent If true, does not notify the navigation helper
321 * of the change.
287 */ 322 */
288 changePage: function(toPage) { 323 changePage: function(newPage, isSilent) {
324 if (this.currentPage_.page == newPage.page &&
325 this.currentPage_.subpage == newPage.subpage &&
326 this.currentPage_.id == newPage.id) {
327 return;
328 }
329
289 this.$.drawer.closeDrawer(); 330 this.$.drawer.closeDrawer();
331 if (this.optionsDialog.open)
332 this.optionsDialog.close();
333
290 var fromPage = this.$.pages.selected; 334 var fromPage = this.$.pages.selected;
291 if (fromPage == toPage) 335 var toPage = newPage.page;
292 return; 336 var data;
293 var entry; 337 if (newPage.id) {
294 var exit; 338 data = this.getData_(newPage.id);
295 if (fromPage == Page.ITEM_LIST && (toPage == Page.DETAIL_VIEW || 339 assert(data, newPage.id);
296 toPage == Page.ERROR_PAGE)) {
297 entry = [extensions.Animation.HERO];
298 // The item grid can be larger than the detail view that we're
299 // hero'ing into, so we want to also fade out to avoid any jarring.
300 exit = [extensions.Animation.HERO, extensions.Animation.FADE_OUT];
301 } else if (toPage == Page.ITEM_LIST) {
302 entry = [extensions.Animation.FADE_IN];
303 exit = [extensions.Animation.SCALE_DOWN];
304 } else {
305 assert(toPage == Page.DETAIL_VIEW ||
306 toPage == Page.KEYBOARD_SHORTCUTS);
307 entry = [extensions.Animation.FADE_IN];
308 exit = [extensions.Animation.FADE_OUT];
309 } 340 }
310 this.getPage_(fromPage).animationHelper.setExitAnimations(exit); 341
311 this.getPage_(toPage).animationHelper.setEntryAnimations(entry); 342 if (toPage == Page.DETAILS) {
312 this.$.pages.selected = toPage; 343 assert(newPage.id);
michaelpg 2017/05/01 23:41:25 throughout this whole function: can you assert on
Devlin 2017/05/02 01:04:07 Done.
344 this.detailViewItem_ = data;
345 } else if (toPage == Page.ERRORS) {
346 assert(newPage.id);
347 this.errorPageItem_ = data;
348 }
349
350 if (fromPage != toPage) {
351 var entry;
michaelpg 2017/05/01 23:41:25 optional: extract this block into a standalone fun
Devlin 2017/05/02 01:04:06 I think that since it's only used here, relies on
michaelpg 2017/05/02 20:58:09 Acknowledged.
352 var exit;
353 if (fromPage == Page.LIST && (toPage == Page.DETAILS ||
354 toPage == Page.ERRORS)) {
355 assert(newPage.id);
michaelpg 2017/05/01 23:41:25 duplicate assertion?
Devlin 2017/05/02 01:04:06 Removed.
356 this.$['items-list'].willShowItemSubpage(data.id);
357 entry = [extensions.Animation.HERO];
358 // The item grid can be larger than the detail view that we're
359 // hero'ing into, so we want to also fade out to avoid any jarring.
360 exit = [extensions.Animation.HERO, extensions.Animation.FADE_OUT];
361 } else if (toPage == Page.LIST) {
362 entry = [extensions.Animation.FADE_IN];
363 exit = [extensions.Animation.SCALE_DOWN];
364 } else {
365 assert(toPage == Page.DETAILS ||
366 toPage == Page.SHORTCUTS);
367 entry = [extensions.Animation.FADE_IN];
368 exit = [extensions.Animation.FADE_OUT];
369 }
370
371 this.getPage_(fromPage).animationHelper.setExitAnimations(exit);
372 this.getPage_(toPage).animationHelper.setEntryAnimations(entry);
373 this.$.pages.selected = toPage;
374 }
375
376 if (newPage.subpage) {
377 assert(newPage.subpage == Dialog.OPTIONS);
378 assert(newPage.id);
379 this.optionsDialog.show(data);
380 }
381
382 this.currentPage_ = newPage;
383
384 if (!isSilent)
385 this.navigationHelper_.updateHistory(newPage);
313 }, 386 },
314 387
315 /** 388 /**
316 * Handles the event for the user clicking on a details button. 389 * Handles the event for the user clicking on a details button.
317 * @param {!CustomEvent} e 390 * @param {!CustomEvent} e
318 * @private 391 * @private
319 */ 392 */
320 onShouldShowItemDetails_: function(e) { 393 onShouldShowItemDetails_: function(e) {
321 this.showItemDetails(e.detail.data); 394 this.showItemDetails(e.detail.data);
322 }, 395 },
323 396
324 /** 397 /**
325 * Handles the event for the user clicking on the errors button. 398 * Handles the event for the user clicking on the errors button.
326 * @param {!CustomEvent} e 399 * @param {!CustomEvent} e
327 * @private 400 * @private
328 */ 401 */
329 onShouldShowItemErrors_: function(e) { 402 onShouldShowItemErrors_: function(e) {
330 var data = e.detail.data; 403 this.changePage({page: Page.ERRORS, id: e.detail.data.id});
331 this.$['items-list'].willShowItemSubpage(data.id);
332 this.errorPageItem_ = data;
333 this.changePage(Page.ERROR_PAGE);
334 }, 404 },
335 405
336 /** @private */ 406 /** @private */
337 onDetailsViewClose_: function() { 407 onDetailsViewClose_: function() {
338 // Note: we don't reset detailViewItem_ here because doing so just causes 408 // Note: we don't reset detailViewItem_ here because doing so just causes
339 // extra work for the data-bound details view. 409 // extra work for the data-bound details view.
340 this.changePage(Page.ITEM_LIST); 410 this.changePage({page: Page.LIST});
341 }, 411 },
342 412
343 /** @private */ 413 /** @private */
344 onErrorPageClose_: function() { 414 onErrorPageClose_: function() {
345 // Note: we don't reset errorPageItem_ here because doing so just causes 415 // Note: we don't reset errorPageItem_ here because doing so just causes
346 // extra work for the data-bound error page. 416 // extra work for the data-bound error page.
347 this.changePage(Page.ITEM_LIST); 417 this.changePage({page: Page.LIST});
348 }, 418 },
349 419
350 /** @private */ 420 /** @private */
351 onPackTap_: function() { 421 onPackTap_: function() {
352 this.$['pack-dialog'].show(); 422 this.$['pack-dialog'].show();
353 } 423 }
354 }); 424 });
355 425
356 /** 426 /**
357 * @param {extensions.Manager} manager 427 * @param {extensions.Manager} manager
(...skipping 11 matching lines...) Expand all
369 switch (type) { 439 switch (type) {
370 case extensions.ShowingType.EXTENSIONS: 440 case extensions.ShowingType.EXTENSIONS:
371 items = this.manager_.extensions; 441 items = this.manager_.extensions;
372 break; 442 break;
373 case extensions.ShowingType.APPS: 443 case extensions.ShowingType.APPS:
374 items = this.manager_.apps; 444 items = this.manager_.apps;
375 break; 445 break;
376 } 446 }
377 447
378 this.manager_.$/* hack */ ['items-list'].set('items', assert(items)); 448 this.manager_.$/* hack */ ['items-list'].set('items', assert(items));
379 this.manager_.changePage(Page.ITEM_LIST); 449 this.manager_.changePage({page: Page.LIST});
380 }, 450 },
381 451
382 /** @override */ 452 /** @override */
383 showKeyboardShortcuts: function() { 453 showKeyboardShortcuts: function() {
384 this.manager_.changePage(Page.KEYBOARD_SHORTCUTS); 454 this.manager_.changePage({page: Page.SHORTCUTS});
385 }, 455 },
386 }; 456 };
387 457
388 return {Manager: Manager}; 458 return {Manager: Manager};
389 }); 459 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698