OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 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. |
| 4 |
| 5 /** |
| 6 * The different pages that can be shown at a time. |
| 7 * Note: This must remain in sync with the page ids in manager.html! |
| 8 * @enum {string} |
| 9 */ |
| 10 var Page = { |
| 11 LIST: 'items-list', |
| 12 DETAILS: 'details-view', |
| 13 SHORTCUTS: 'keyboard-shortcuts', |
| 14 ERRORS: 'error-page', |
| 15 }; |
| 16 |
| 17 /** @enum {string} */ |
| 18 var Dialog = { |
| 19 OPTIONS: 'options', |
| 20 }; |
| 21 |
| 22 /** @typedef {{page: Page, |
| 23 extensionId: (string|undefined), |
| 24 subpage: (!Dialog|undefined)}} */ |
| 25 var PageState; |
| 26 |
| 27 cr.define('extensions', function() { |
| 28 'use strict'; |
| 29 |
| 30 /** |
| 31 * A helper object to manage in-page navigations. Since the extensions page |
| 32 * needs to support different urls for different subpages (like the details |
| 33 * page), we use this object to manage the history and url conversions. |
| 34 * @param {!function(!PageState):void} onHistoryChange A function to call when |
| 35 * the page has changed as a result of the user going back or forward in |
| 36 * history; called with the new active page. |
| 37 * @constructor */ |
| 38 function NavigationHelper(onHistoryChange) { |
| 39 this.onHistoryChange_ = onHistoryChange; |
| 40 window.addEventListener('popstate', this.onPopState_.bind(this)); |
| 41 } |
| 42 |
| 43 NavigationHelper.prototype = { |
| 44 /** @private */ |
| 45 onPopState_: function() { |
| 46 this.onHistoryChange_(this.getCurrentPage()); |
| 47 }, |
| 48 |
| 49 /** |
| 50 * Returns the page that should be displayed for the current URL. |
| 51 * @return {!PageState} |
| 52 */ |
| 53 getCurrentPage: function() { |
| 54 var search = new URLSearchParams(location.search); |
| 55 var id = search.get('id'); |
| 56 if (id) |
| 57 return {page: Page.DETAILS, extensionId: id}; |
| 58 id = search.get('options'); |
| 59 if (id) |
| 60 return {page: Page.DETAILS, extensionId: id, subpage: Dialog.OPTIONS}; |
| 61 id = search.get('errors'); |
| 62 if (id) |
| 63 return {page: Page.ERRORS, extensionId: id}; |
| 64 |
| 65 if (location.pathname == '/shortcuts') |
| 66 return {page: Page.SHORTCUTS}; |
| 67 |
| 68 return {page: Page.LIST}; |
| 69 }, |
| 70 |
| 71 /** |
| 72 * Called when a page changes, and pushes state to history to reflect it. |
| 73 * @param {!PageState} entry |
| 74 */ |
| 75 updateHistory: function(entry) { |
| 76 var path; |
| 77 switch (entry.page) { |
| 78 case Page.LIST: |
| 79 path = '/'; |
| 80 break; |
| 81 case Page.DETAILS: |
| 82 if (entry.subpage) { |
| 83 assert(entry.subpage == Dialog.OPTIONS); |
| 84 path = '/?options=' + entry.extensionId; |
| 85 } else { |
| 86 path = '/?id=' + entry.extensionId; |
| 87 } |
| 88 break; |
| 89 case Page.SHORTCUTS: |
| 90 path = '/shortcuts'; |
| 91 break; |
| 92 case Page.ERRORS: |
| 93 path = '/?errors=' + entry.extensionId; |
| 94 break; |
| 95 } |
| 96 assert(path); |
| 97 var state = {url: path}; |
| 98 var currentPage = this.getCurrentPage(); |
| 99 var isDialogNavigation = |
| 100 currentPage.page == entry.page && |
| 101 currentPage.extensionId == entry.extensionId; |
| 102 // Navigating to a dialog doesn't visually change pages; it just opens |
| 103 // a dialog. As such, we replace state rather than pushing a new state |
| 104 // on the stack so that hitting the back button doesn't just toggle the |
| 105 // dialog. |
| 106 if (isDialogNavigation) |
| 107 history.replaceState(state, '', path); |
| 108 else |
| 109 history.pushState(state, '', path); |
| 110 }, |
| 111 }; |
| 112 |
| 113 return {NavigationHelper: NavigationHelper}; |
| 114 }); |
OLD | NEW |