Chromium Code Reviews| Index: chrome/browser/resources/md_extensions/navigation_helper.js |
| diff --git a/chrome/browser/resources/md_extensions/navigation_helper.js b/chrome/browser/resources/md_extensions/navigation_helper.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..d22e9a7d89616bd427aa72037f5c9a45fd2db06d |
| --- /dev/null |
| +++ b/chrome/browser/resources/md_extensions/navigation_helper.js |
| @@ -0,0 +1,116 @@ |
| +// Copyright 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +/** |
| + * The different pages that can be shown at a time. |
| + * Note: This must remain in sync with the order in manager.html! |
|
michaelpg
2017/05/01 23:41:25
with the page ids
Devlin
2017/05/02 01:04:07
Done.
|
| + * @enum {string} |
| + */ |
| +var Page = { |
| + LIST: 'items-list', |
| + DETAILS: 'details-view', |
| + SHORTCUTS: 'keyboard-shortcuts', |
| + ERRORS: 'error-page', |
| +}; |
| + |
| +/** @enum {string} */ |
| +var Dialog = { |
| + OPTIONS: 'options', |
| +}; |
| + |
| +/** @typedef {{page: Page, |
| + id: (string|undefined), |
|
michaelpg
2017/05/01 23:41:25
You probably have this problem all throughout exte
Devlin
2017/05/02 01:04:07
done.
|
| + subpage: (!Dialog|undefined)}} */ |
| +var PageState; |
| + |
| +cr.define('extensions', function() { |
| + 'use strict'; |
| + |
| + /** |
| + * A helper object to manage in-page navigations. Since the extensions page |
| + * needs to support different urls for different subpages (like the details |
| + * page), we use this object to manage the history and url conversions. |
| + * @param {!function(!PageState):void} onHistoryChange A function to call when |
| + * the page has changed as a result of the user going back or forward in |
| + * history; called with the new active page. |
| + * @constructor */ |
| + function NavigationHelper(onHistoryChange) { |
| + this.onHistoryChange_ = onHistoryChange; |
| + window.addEventListener('popstate', this.onPopState_.bind(this)); |
| + } |
| + |
| + NavigationHelper.prototype = { |
| + /** @private */ |
| + onPopState_: function() { |
| + this.onHistoryChange_(this.getCurrentPage()); |
| + }, |
| + |
| + /** |
| + * Returns the page that should be displayed for the current URL. |
| + * @return {!PageState} |
| + */ |
| + getCurrentPage: function() { |
| + if (location.search == '' && location.pathname == '/') |
|
michaelpg
2017/05/01 23:41:25
i'd be in favor of removing this, as it's already
Devlin
2017/05/02 01:04:07
Done.
|
| + return {page: Page.LIST}; |
| + |
| + var search = new URLSearchParams(location.search); |
| + var id = search.get('id'); |
| + if (id) |
| + return {page: Page.DETAILS, id: id}; |
| + id = search.get('options'); |
| + if (id) |
| + return {page: Page.DETAILS, id: id, subpage: Dialog.OPTIONS}; |
| + id = search.get('errors'); |
| + if (id) |
| + return {page: Page.ERRORS, id: id}; |
| + |
| + if (location.pathname == '/shortcuts') |
| + return {page: Page.SHORTCUTS}; |
| + |
| + return {page: Page.LIST}; |
| + }, |
| + |
| + /** |
| + * Called when a page changes, and pushes state to history to reflect it. |
| + * @param {!PageState} entry |
| + */ |
| + updateHistory: function(entry) { |
| + var relative; |
|
michaelpg
2017/05/01 23:41:25
absolute? :-\
Devlin
2017/05/02 01:04:07
s/relative/path
|
| + switch (entry.page) { |
| + case Page.LIST: |
| + relative = '/'; |
| + break; |
| + case Page.DETAILS: |
| + if (entry.subpage) { |
| + assert(entry.subpage == Dialog.OPTIONS); |
| + relative = '/?options=' + entry.id; |
| + } else { |
| + relative = '/?id=' + entry.id; |
| + } |
| + break; |
| + case Page.SHORTCUTS: |
| + relative = '/shortcuts'; |
| + break; |
| + case Page.ERRORS: |
| + relative = '/?errors=' + entry.id; |
|
michaelpg
2017/05/01 23:41:25
add a break; so adding another case doesn't cause
Devlin
2017/05/02 01:04:07
Done.
|
| + } |
| + assert(relative); |
| + var state = {url: relative}; |
| + var currentPage = this.getCurrentPage(); |
| + var isDialogNavigation = |
| + currentPage.page == entry.page && |
| + currentPage.id == entry.id; |
| + // Navigating to a dialog doesn't visually change pages; it just opens |
| + // a dialog. As such, we replace state rather than pushing a new state |
| + // on the stack so that hitting the back button doesn't just toggle the |
| + // dialog. |
| + if (isDialogNavigation) |
| + history.replaceState(state, '', relative); |
| + else |
| + history.pushState(state, '', relative); |
| + }, |
| + }; |
| + |
| + return {NavigationHelper: NavigationHelper}; |
| +}); |