| 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..e58107fdad65d5248255b50872230f5bdd1a519b
|
| --- /dev/null
|
| +++ b/chrome/browser/resources/md_extensions/navigation_helper.js
|
| @@ -0,0 +1,114 @@
|
| +// 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 page ids in manager.html!
|
| + * @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,
|
| + extensionId: (string|undefined),
|
| + 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() {
|
| + var search = new URLSearchParams(location.search);
|
| + var id = search.get('id');
|
| + if (id)
|
| + return {page: Page.DETAILS, extensionId: id};
|
| + id = search.get('options');
|
| + if (id)
|
| + return {page: Page.DETAILS, extensionId: id, subpage: Dialog.OPTIONS};
|
| + id = search.get('errors');
|
| + if (id)
|
| + return {page: Page.ERRORS, extensionId: 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 path;
|
| + switch (entry.page) {
|
| + case Page.LIST:
|
| + path = '/';
|
| + break;
|
| + case Page.DETAILS:
|
| + if (entry.subpage) {
|
| + assert(entry.subpage == Dialog.OPTIONS);
|
| + path = '/?options=' + entry.extensionId;
|
| + } else {
|
| + path = '/?id=' + entry.extensionId;
|
| + }
|
| + break;
|
| + case Page.SHORTCUTS:
|
| + path = '/shortcuts';
|
| + break;
|
| + case Page.ERRORS:
|
| + path = '/?errors=' + entry.extensionId;
|
| + break;
|
| + }
|
| + assert(path);
|
| + var state = {url: path};
|
| + var currentPage = this.getCurrentPage();
|
| + var isDialogNavigation =
|
| + currentPage.page == entry.page &&
|
| + currentPage.extensionId == entry.extensionId;
|
| + // 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, '', path);
|
| + else
|
| + history.pushState(state, '', path);
|
| + },
|
| + };
|
| +
|
| + return {NavigationHelper: NavigationHelper};
|
| +});
|
|
|