/**
 * @license
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
(function() {
  'use strict';

  const RoutePattern = {
    ROOT: '/',

    DASHBOARD: /^\/dashboard\/(.+)$/,
    CUSTOM_DASHBOARD: /^\/dashboard\/?$/,
    PROJECT_DASHBOARD: /^\/p\/(.+)\/\+\/dashboard\/(.+)/,

    AGREEMENTS: /^\/settings\/agreements\/?/,
    NEW_AGREEMENTS: /^\/settings\/new-agreement\/?/,
    REGISTER: /^\/register(\/.*)?$/,

    // Pattern for login and logout URLs intended to be passed-through. May
    // include a return URL.
    LOG_IN_OR_OUT: /\/log(in|out)(\/(.+))?$/,

    // Pattern for a catchall route when no other pattern is matched.
    DEFAULT: /.*/,

    // Matches /admin/groups/[uuid-]<group>
    GROUP: /^\/admin\/groups\/(?:uuid-)?([^,]+)$/,

    // Redirects /groups/self to /settings/#Groups for GWT compatibility
    GROUP_SELF: /^\/groups\/self/,

    // Matches /admin/groups/[uuid-]<group>,info (backwords compat with gwtui)
    // Redirects to /admin/groups/[uuid-]<group>
    GROUP_INFO: /^\/admin\/groups\/(?:uuid-)?(.+),info$/,

    // Matches /admin/groups/<group>,audit-log
    GROUP_AUDIT_LOG: /^\/admin\/groups\/(?:uuid-)?(.+),audit-log$/,

    // Matches /admin/groups/[uuid-]<group>,members
    GROUP_MEMBERS: /^\/admin\/groups\/(?:uuid-)?(.+),members$/,

    // Matches /admin/groups[,<offset>][/].
    GROUP_LIST_OFFSET: /^\/admin\/groups(,(\d+))?(\/)?$/,
    GROUP_LIST_FILTER: '/admin/groups/q/filter::filter',
    GROUP_LIST_FILTER_OFFSET: '/admin/groups/q/filter::filter,:offset',

    // Matches /admin/create-project
    LEGACY_CREATE_PROJECT: /^\/admin\/create-project\/?$/,

    // Matches /admin/create-project
    LEGACY_CREATE_GROUP: /^\/admin\/create-group\/?$/,

    PROJECT_OLD: /^\/admin\/(projects)\/?(.+)?$/,

    // Matches /admin/repos/<repo>
    REPO: /^\/admin\/repos\/([^,]+)$/,

    // Matches /admin/repos/<repo>,commands.
    REPO_COMMANDS: /^\/admin\/repos\/(.+),commands$/,

    // Matches /admin/repos/<repos>,access.
    REPO_ACCESS: /^\/admin\/repos\/(.+),access$/,

    // Matches /admin/repos/<repos>,access.
    REPO_DASHBOARDS: /^\/admin\/repos\/(.+),dashboards$/,

    // Matches /admin/repos[,<offset>][/].
    REPO_LIST_OFFSET: /^\/admin\/repos(,(\d+))?(\/)?$/,
    REPO_LIST_FILTER: '/admin/repos/q/filter::filter',
    REPO_LIST_FILTER_OFFSET: '/admin/repos/q/filter::filter,:offset',

    // Matches /admin/repos/<repo>,branches[,<offset>].
    BRANCH_LIST_OFFSET: /^\/admin\/repos\/(.+),branches(,(.+))?$/,
    BRANCH_LIST_FILTER: '/admin/repos/:repo,branches/q/filter::filter',
    BRANCH_LIST_FILTER_OFFSET:
        '/admin/repos/:repo,branches/q/filter::filter,:offset',

    // Matches /admin/repos/<repo>,tags[,<offset>].
    TAG_LIST_OFFSET: /^\/admin\/repos\/(.+),tags(,(.+))?$/,
    TAG_LIST_FILTER: '/admin/repos/:repo,tags/q/filter::filter',
    TAG_LIST_FILTER_OFFSET:
        '/admin/repos/:repo,tags/q/filter::filter,:offset',

    PLUGINS: /^\/plugins\/(.+)$/,

    PLUGIN_LIST: /^\/admin\/plugins(\/)?$/,

    // Matches /admin/plugins[,<offset>][/].
    PLUGIN_LIST_OFFSET: /^\/admin\/plugins(,(\d+))?(\/)?$/,
    PLUGIN_LIST_FILTER: '/admin/plugins/q/filter::filter',
    PLUGIN_LIST_FILTER_OFFSET: '/admin/plugins/q/filter::filter,:offset',

    QUERY: /^\/q\/([^,]+)(,(\d+))?$/,

    /**
     * Support vestigial params from GWT UI.
     * @see Issue 7673.
     * @type {!RegExp}
     */
    QUERY_LEGACY_SUFFIX: /^\/q\/.+,n,z$/,

    // Matches /c/<changeNum>/[<basePatchNum>..][<patchNum>][/].
    CHANGE_LEGACY: /^\/c\/(\d+)\/?(((-?\d+|edit)(\.\.(\d+|edit))?))?\/?$/,
    CHANGE_NUMBER_LEGACY: /^\/(\d+)\/?/,

    // Matches
    // /c/<project>/+/<changeNum>/[<basePatchNum|edit>..][<patchNum|edit>].
    // TODO(kaspern): Migrate completely to project based URLs, with backwards
    // compatibility for change-only.
    CHANGE: /^\/c\/(.+)\/\+\/(\d+)(\/?((-?\d+|edit)(\.\.(\d+|edit))?))?\/?$/,

    // Matches /c/<project>/+/<changeNum>/[<patchNum|edit>],edit
    CHANGE_EDIT: /^\/c\/(.+)\/\+\/(\d+)(\/(\d+))?,edit\/?$/,

    // Matches
    // /c/<project>/+/<changeNum>/[<basePatchNum|edit>..]<patchNum|edit>/<path>.
    // TODO(kaspern): Migrate completely to project based URLs, with backwards
    // compatibility for change-only.
    // eslint-disable-next-line max-len
    DIFF: /^\/c\/(.+)\/\+\/(\d+)(\/((-?\d+|edit)(\.\.(\d+|edit))?(\/(.+))))\/?$/,

    // Matches /c/<project>/+/<changeNum>/[<patchNum|edit>]/<path>,edit
    DIFF_EDIT: /^\/c\/(.+)\/\+\/(\d+)\/(\d+|edit)\/(.+),edit$/,

    // Matches non-project-relative
    // /c/<changeNum>/[<basePatchNum>..]<patchNum>/<path>.
    DIFF_LEGACY: /^\/c\/(\d+)\/((-?\d+|edit)(\.\.(\d+|edit))?)\/(.+)/,

    // Matches diff routes using @\d+ to specify a file name (whether or not
    // the project name is included).
    // eslint-disable-next-line max-len
    DIFF_LEGACY_LINENUM: /^\/c\/((.+)\/\+\/)?(\d+)(\/?((-?\d+|edit)(\.\.(\d+|edit))?\/(.+))?)@[ab]?\d+$/,

    SETTINGS: /^\/settings\/?/,
    SETTINGS_LEGACY: /^\/settings\/VE\/(\S+)/,

    // Matches /c/<changeNum>/ /<URL tail>
    // Catches improperly encoded URLs (context: Issue 7100)
    IMPROPERLY_ENCODED_PLUS: /^\/c\/(.+)\/\ \/(.+)$/,

    PLUGIN_SCREEN: /^\/x\/([\w-]+)\/([\w-]+)\/?/,

    DOCUMENTATION_SEARCH_FILTER: '/Documentation/q/filter::filter',
    DOCUMENTATION_SEARCH: /^\/Documentation\/q\/(.*)$/,
    DOCUMENTATION: /^\/Documentation(\/)?(.+)?/,
  };

  /**
   * Pattern to recognize and parse the diff line locations as they appear in
   * the hash of diff URLs. In this format, a number on its own indicates that
   * line number in the revision of the diff. A number prefixed by either an 'a'
   * or a 'b' indicates that line number of the base of the diff.
   * @type {RegExp}
   */
  const LINE_ADDRESS_PATTERN = /^([ab]?)(\d+)$/;

  /**
   * Pattern to recognize '+' in url-encoded strings for replacement with ' '.
   */
  const PLUS_PATTERN = /\+/g;

  /**
   * Pattern to recognize leading '?' in window.location.search, for stripping.
   */
  const QUESTION_PATTERN = /^\?*/;

  /**
   * GWT UI would use @\d+ at the end of a path to indicate linenum.
   */
  const LEGACY_LINENUM_PATTERN = /@([ab]?\d+)$/;

  const LEGACY_QUERY_SUFFIX_PATTERN = /,n,z$/;

  const REPO_TOKEN_PATTERN = /\$\{(project|repo)\}/g;

  // Polymer makes `app` intrinsically defined on the window by virtue of the
  // custom element having the id "app", but it is made explicit here.
  const app = document.querySelector('#app');
  if (!app) {
    console.log('No gr-app found (running tests)');
  }

  // Setup listeners outside of the router component initialization.
  (function() {
    const reporting = document.createElement('gr-reporting');

    window.addEventListener('load', () => {
      reporting.pageLoaded();
    });

    window.addEventListener('WebComponentsReady', () => {
      reporting.timeEnd('WebComponentsReady');
    });
  })();

  Polymer({
    is: 'gr-router',
    _legacyUndefinedCheck: true,

    properties: {
      _app: {
        type: Object,
        value: app,
      },
      _isRedirecting: Boolean,
      // This variable is to differentiate between internal navigation (false)
      // and for first navigation in app after loaded from server (true).
      _isInitialLoad: {
        type: Boolean,
        value: true,
      },
    },

    behaviors: [
      Gerrit.BaseUrlBehavior,
      Gerrit.PatchSetBehavior,
      Gerrit.URLEncodingBehavior,
    ],

    start() {
      if (!this._app) { return; }
      this._startRouter();
    },

    _setParams(params) {
      this._appElement().params = params;
    },

    _appElement() {
      // In Polymer2 you have to reach through the shadow root of the app
      // element. This obviously breaks encapsulation.
      // TODO(brohlfs): Make this more elegant, e.g. by exposing app-element
      // explicitly in app, or by delegating to it.
      return document.getElementById('app-element') ||
          document.getElementById('app').shadowRoot.getElementById(
              'app-element');
    },

    _redirect(url) {
      this._isRedirecting = true;
      page.redirect(url);
    },

    /**
     * @param {!Object} params
     * @return {string}
     */
    _generateUrl(params) {
      const base = this.getBaseUrl();
      let url = '';
      const Views = Gerrit.Nav.View;

      if (params.view === Views.SEARCH) {
        url = this._generateSearchUrl(params);
      } else if (params.view === Views.CHANGE) {
        url = this._generateChangeUrl(params);
      } else if (params.view === Views.DASHBOARD) {
        url = this._generateDashboardUrl(params);
      } else if (params.view === Views.DIFF || params.view === Views.EDIT) {
        url = this._generateDiffOrEditUrl(params);
      } else if (params.view === Views.GROUP) {
        url = this._generateGroupUrl(params);
      } else if (params.view === Views.REPO) {
        url = this._generateRepoUrl(params);
      } else if (params.view === Views.ROOT) {
        url = '/';
      } else if (params.view === Views.SETTINGS) {
        url = this._generateSettingsUrl(params);
      } else {
        throw new Error('Can\'t generate');
      }

      return base + url;
    },

    _generateWeblinks(params) {
      const type = params.type;
      switch (type) {
        case Gerrit.Nav.WeblinkType.FILE:
          return this._getFileWebLinks(params);
        case Gerrit.Nav.WeblinkType.CHANGE:
          return this._getChangeWeblinks(params);
        case Gerrit.Nav.WeblinkType.PATCHSET:
          return this._getPatchSetWeblink(params);
        default:
          console.warn(`Unsupported weblink ${type}!`);
      }
    },

    _getPatchSetWeblink(params) {
      const {commit, options} = params;
      const {weblinks, config} = options || {};
      const name = commit && commit.slice(0, 7);
      const weblink = this._getBrowseCommitWeblink(weblinks, config);
      if (!weblink || !weblink.url) {
        return {name};
      } else {
        return {name, url: weblink.url};
      }
    },

    _firstCodeBrowserWeblink(weblinks) {
      // This is an ordered whitelist of web link types that provide direct
      // links to the commit in the url property.
      const codeBrowserLinks = ['gitiles', 'browse', 'gitweb'];
      for (let i = 0; i < codeBrowserLinks.length; i++) {
        const weblink =
          weblinks.find(weblink => weblink.name === codeBrowserLinks[i]);
        if (weblink) { return weblink; }
      }
      return null;
    },


    _getBrowseCommitWeblink(weblinks, config) {
      if (!weblinks) { return null; }
      let weblink;
      // Use primary weblink if configured and exists.
      if (config && config.gerrit && config.gerrit.primary_weblink_name) {
        weblink = weblinks.find(
            weblink => weblink.name === config.gerrit.primary_weblink_name
        );
      }
      if (!weblink) {
        weblink = this._firstCodeBrowserWeblink(weblinks);
      }
      if (!weblink) { return null; }
      return weblink;
    },

    _getChangeWeblinks({repo, commit, options: {weblinks, config}}) {
      if (!weblinks || !weblinks.length) return [];
      const commitWeblink = this._getBrowseCommitWeblink(weblinks, config);
      return weblinks.filter(weblink =>
        !commitWeblink ||
        !commitWeblink.name ||
        weblink.name !== commitWeblink.name);
    },

    _getFileWebLinks({repo, commit, file, options: {weblinks}}) {
      return weblinks;
    },

    /**
     * @param {!Object} params
     * @return {string}
     */
    _generateSearchUrl(params) {
      let offsetExpr = '';
      if (params.offset && params.offset > 0) {
        offsetExpr = ',' + params.offset;
      }

      if (params.query) {
        return '/q/' + this.encodeURL(params.query, true) + offsetExpr;
      }

      const operators = [];
      if (params.owner) {
        operators.push('owner:' + this.encodeURL(params.owner, false));
      }
      if (params.project) {
        operators.push('project:' + this.encodeURL(params.project, false));
      }
      if (params.branch) {
        operators.push('branch:' + this.encodeURL(params.branch, false));
      }
      if (params.topic) {
        operators.push('topic:"' + this.encodeURL(params.topic, false) + '"');
      }
      if (params.hashtag) {
        operators.push('hashtag:"' +
            this.encodeURL(params.hashtag.toLowerCase(), false) + '"');
      }
      if (params.statuses) {
        if (params.statuses.length === 1) {
          operators.push(
              'status:' + this.encodeURL(params.statuses[0], false));
        } else if (params.statuses.length > 1) {
          operators.push(
              '(' +
              params.statuses.map(s => `status:${this.encodeURL(s, false)}`)
                  .join(' OR ') +
              ')');
        }
      }

      return '/q/' + operators.join('+') + offsetExpr;
    },

    /**
     * @param {!Object} params
     * @return {string}
     */
    _generateChangeUrl(params) {
      let range = this._getPatchRangeExpression(params);
      if (range.length) { range = '/' + range; }
      let suffix = `${range}`;
      if (params.querystring) {
        suffix += '?' + params.querystring;
      } else if (params.edit) {
        suffix += ',edit';
      }
      if (params.messageHash) {
        suffix += params.messageHash;
      }
      if (params.project) {
        const encodedProject = this.encodeURL(params.project, true);
        return `/c/${encodedProject}/+/${params.changeNum}${suffix}`;
      } else {
        return `/c/${params.changeNum}${suffix}`;
      }
    },

    /**
     * @param {!Object} params
     * @return {string}
     */
    _generateDashboardUrl(params) {
      const repoName = params.repo || params.project || null;
      if (params.sections) {
        // Custom dashboard.
        const queryParams = this._sectionsToEncodedParams(params.sections,
            repoName);
        if (params.title) {
          queryParams.push('title=' + encodeURIComponent(params.title));
        }
        const user = params.user ? params.user : '';
        return `/dashboard/${user}?${queryParams.join('&')}`;
      } else if (repoName) {
        // Project dashboard.
        const encodedRepo = this.encodeURL(repoName, true);
        return `/p/${encodedRepo}/+/dashboard/${params.dashboard}`;
      } else {
        // User dashboard.
        return `/dashboard/${params.user || 'self'}`;
      }
    },

    /**
     * @param {!Array<!{name: string, query: string}>} sections
     * @param {string=} opt_repoName
     * @return {!Array<string>}
     */
    _sectionsToEncodedParams(sections, opt_repoName) {
      return sections.map(section => {
        // If there is a repo name provided, make sure to substitute it into the
        // ${repo} (or legacy ${project}) query tokens.
        const query = opt_repoName ?
            section.query.replace(REPO_TOKEN_PATTERN, opt_repoName) :
            section.query;
        return encodeURIComponent(section.name) + '=' +
            encodeURIComponent(query);
      });
    },

    /**
     * @param {!Object} params
     * @return {string}
     */
    _generateDiffOrEditUrl(params) {
      let range = this._getPatchRangeExpression(params);
      if (range.length) { range = '/' + range; }

      let suffix = `${range}/${this.encodeURL(params.path, true)}`;

      if (params.view === Gerrit.Nav.View.EDIT) { suffix += ',edit'; }

      if (params.lineNum) {
        suffix += '#';
        if (params.leftSide) { suffix += 'b'; }
        suffix += params.lineNum;
      }

      if (params.project) {
        const encodedProject = this.encodeURL(params.project, true);
        return `/c/${encodedProject}/+/${params.changeNum}${suffix}`;
      } else {
        return `/c/${params.changeNum}${suffix}`;
      }
    },

    /**
     * @param {!Object} params
     * @return {string}
     */
    _generateGroupUrl(params) {
      let url = `/admin/groups/${this.encodeURL(params.groupId + '', true)}`;
      if (params.detail === Gerrit.Nav.GroupDetailView.MEMBERS) {
        url += ',members';
      } else if (params.detail === Gerrit.Nav.GroupDetailView.LOG) {
        url += ',audit-log';
      }
      return url;
    },

    /**
     * @param {!Object} params
     * @return {string}
     */
    _generateRepoUrl(params) {
      let url = `/admin/repos/${this.encodeURL(params.repoName + '', true)}`;
      if (params.detail === Gerrit.Nav.RepoDetailView.ACCESS) {
        url += ',access';
      } else if (params.detail === Gerrit.Nav.RepoDetailView.BRANCHES) {
        url += ',branches';
      } else if (params.detail === Gerrit.Nav.RepoDetailView.TAGS) {
        url += ',tags';
      } else if (params.detail === Gerrit.Nav.RepoDetailView.COMMANDS) {
        url += ',commands';
      } else if (params.detail === Gerrit.Nav.RepoDetailView.DASHBOARDS) {
        url += ',dashboards';
      }
      return url;
    },

    /**
     * @param {!Object} params
     * @return {string}
     */
    _generateSettingsUrl(params) {
      return '/settings';
    },

    /**
     * Given an object of parameters, potentially including a `patchNum` or a
     * `basePatchNum` or both, return a string representation of that range. If
     * no range is indicated in the params, the empty string is returned.
     * @param {!Object} params
     * @return {string}
     */
    _getPatchRangeExpression(params) {
      let range = '';
      if (params.patchNum) { range = '' + params.patchNum; }
      if (params.basePatchNum) { range = params.basePatchNum + '..' + range; }
      return range;
    },

    /**
     * Given a set of params without a project, gets the project from the rest
     * API project lookup and then sets the app params.
     *
     * @param {?Object} params
     */
    _normalizeLegacyRouteParams(params) {
      if (!params.changeNum) { return Promise.resolve(); }

      return this.$.restAPI.getFromProjectLookup(params.changeNum)
          .then(project => {
            // Show a 404 and terminate if the lookup request failed. Attempting
            // to redirect after failing to get the project loops infinitely.
            if (!project) {
              this._show404();
              return;
            }

            params.project = project;
            this._normalizePatchRangeParams(params);
            this._redirect(this._generateUrl(params));
          });
    },

    /**
     * Normalizes the params object, and determines if the URL needs to be
     * modified to fit the proper schema.
     *
     * @param {*} params
     * @return {boolean} whether or not the URL needs to be upgraded.
     */
    _normalizePatchRangeParams(params) {
      const hasBasePatchNum = params.basePatchNum !== null &&
          params.basePatchNum !== undefined;
      const hasPatchNum = params.patchNum !== null &&
          params.patchNum !== undefined;
      let needsRedirect = false;

      // Diffing a patch against itself is invalid, so if the base and revision
      // patches are equal clear the base.
      if (hasBasePatchNum &&
          this.patchNumEquals(params.basePatchNum, params.patchNum)) {
        needsRedirect = true;
        params.basePatchNum = null;
      } else if (hasBasePatchNum && !hasPatchNum) {
        // Regexes set basePatchNum instead of patchNum when only one is
        // specified. Redirect is not needed in this case.
        params.patchNum = params.basePatchNum;
        params.basePatchNum = null;
      }
      // In GWTUI, edits are represented in URLs with either 0 or 'edit'.
      // TODO(kaspern): Remove this normalization when GWT UI is gone.
      if (this.patchNumEquals(params.basePatchNum, 0)) {
        params.basePatchNum = this.EDIT_NAME;
        needsRedirect = true;
      }
      if (this.patchNumEquals(params.patchNum, 0)) {
        params.patchNum = this.EDIT_NAME;
        needsRedirect = true;
      }
      return needsRedirect;
    },

    /**
     * Redirect the user to login using the given return-URL for redirection
     * after authentication success.
     * @param {string} returnUrl
     */
    _redirectToLogin(returnUrl) {
      const basePath = this.getBaseUrl() || '';
      page(
          '/login/' + encodeURIComponent(returnUrl.substring(basePath.length)));
    },

    /**
     * Hashes parsed by page.js exclude "inner" hashes, so a URL like "/a#b#c"
     * is parsed to have a hash of "b" rather than "b#c". Instead, this method
     * parses hashes correctly. Will return an empty string if there is no hash.
     * @param {!string} canonicalPath
     * @return {!string} Everything after the first '#' ("a#b#c" -> "b#c").
     */
    _getHashFromCanonicalPath(canonicalPath) {
      return canonicalPath.split('#').slice(1).join('#');
    },

    _parseLineAddress(hash) {
      const match = hash.match(LINE_ADDRESS_PATTERN);
      if (!match) { return null; }
      return {
        leftSide: !!match[1],
        lineNum: parseInt(match[2], 10),
      };
    },

    /**
     * Check to see if the user is logged in and return a promise that only
     * resolves if the user is logged in. If the user us not logged in, the
     * promise is rejected and the page is redirected to the login flow.
     * @param {!Object} data The parsed route data.
     * @return {!Promise<!Object>} A promise yielding the original route data
     *     (if it resolves).
     */
    _redirectIfNotLoggedIn(data) {
      return this.$.restAPI.getLoggedIn().then(loggedIn => {
        if (loggedIn) {
          return Promise.resolve();
        } else {
          this._redirectToLogin(data.canonicalPath);
          return Promise.reject(new Error());
        }
      });
    },

    /**  Page.js middleware that warms the REST API's logged-in cache line. */
    _loadUserMiddleware(ctx, next) {
      this.$.restAPI.getLoggedIn().then(() => { next(); });
    },

    /**
     * Map a route to a method on the router.
     *
     * @param {!string|!RegExp} pattern The page.js pattern for the route.
     * @param {!string} handlerName The method name for the handler. If the
     *     route is matched, the handler will be executed with `this` referring
     *     to the component. Its return value will be discarded so that it does
     *     not interfere with page.js.
     * @param  {?boolean=} opt_authRedirect If true, then auth is checked before
     *     executing the handler. If the user is not logged in, it will redirect
     *     to the login flow and the handler will not be executed. The login
     *     redirect specifies the matched URL to be used after successfull auth.
     */
    _mapRoute(pattern, handlerName, opt_authRedirect) {
      if (!this[handlerName]) {
        console.error('Attempted to map route to unknown method: ',
            handlerName);
        return;
      }
      page(pattern, this._loadUserMiddleware.bind(this), data => {
        this.$.reporting.locationChanged(handlerName);
        const promise = opt_authRedirect ?
          this._redirectIfNotLoggedIn(data) : Promise.resolve();
        promise.then(() => { this[handlerName](data); });
      });
    },

    _startRouter() {
      const base = this.getBaseUrl();
      if (base) {
        page.base(base);
      }

      Gerrit.Nav.setup(
          url => { page.show(url); },
          this._generateUrl.bind(this),
          params => this._generateWeblinks(params),
          x => x
      );

      page.exit('*', (ctx, next) => {
        if (!this._isRedirecting) {
          this.$.reporting.beforeLocationChanged();
        }
        this._isRedirecting = false;
        this._isInitialLoad = false;
        next();
      });

      // Middleware
      page((ctx, next) => {
        document.body.scrollTop = 0;

        if (ctx.hash.match(RoutePattern.PLUGIN_SCREEN)) {
          // Redirect all urls using hash #/x/plugin/screen to /x/plugin/screen
          // This is needed to allow plugins to add basic #/x/ screen links to
          // any location.
          this._redirect(ctx.hash);
          return;
        }

        // Fire asynchronously so that the URL is changed by the time the event
        // is processed.
        this.async(() => {
          this.fire('location-change', {
            hash: window.location.hash,
            pathname: window.location.pathname,
          });
        }, 1);
        next();
      });

      this._mapRoute(RoutePattern.ROOT, '_handleRootRoute');

      this._mapRoute(RoutePattern.DASHBOARD, '_handleDashboardRoute');

      this._mapRoute(RoutePattern.CUSTOM_DASHBOARD,
          '_handleCustomDashboardRoute');

      this._mapRoute(RoutePattern.PROJECT_DASHBOARD,
          '_handleProjectDashboardRoute');

      this._mapRoute(RoutePattern.GROUP_INFO, '_handleGroupInfoRoute', true);

      this._mapRoute(RoutePattern.GROUP_AUDIT_LOG, '_handleGroupAuditLogRoute',
          true);

      this._mapRoute(RoutePattern.GROUP_MEMBERS, '_handleGroupMembersRoute',
          true);

      this._mapRoute(RoutePattern.GROUP_LIST_OFFSET,
          '_handleGroupListOffsetRoute', true);

      this._mapRoute(RoutePattern.GROUP_LIST_FILTER_OFFSET,
          '_handleGroupListFilterOffsetRoute', true);

      this._mapRoute(RoutePattern.GROUP_LIST_FILTER,
          '_handleGroupListFilterRoute', true);

      this._mapRoute(RoutePattern.GROUP_SELF, '_handleGroupSelfRedirectRoute',
          true);

      this._mapRoute(RoutePattern.GROUP, '_handleGroupRoute', true);

      this._mapRoute(RoutePattern.PROJECT_OLD,
          '_handleProjectsOldRoute');

      this._mapRoute(RoutePattern.REPO_COMMANDS,
          '_handleRepoCommandsRoute', true);

      this._mapRoute(RoutePattern.REPO_ACCESS,
          '_handleRepoAccessRoute');

      this._mapRoute(RoutePattern.REPO_DASHBOARDS,
          '_handleRepoDashboardsRoute');

      this._mapRoute(RoutePattern.BRANCH_LIST_OFFSET,
          '_handleBranchListOffsetRoute');

      this._mapRoute(RoutePattern.BRANCH_LIST_FILTER_OFFSET,
          '_handleBranchListFilterOffsetRoute');

      this._mapRoute(RoutePattern.BRANCH_LIST_FILTER,
          '_handleBranchListFilterRoute');

      this._mapRoute(RoutePattern.TAG_LIST_OFFSET,
          '_handleTagListOffsetRoute');

      this._mapRoute(RoutePattern.TAG_LIST_FILTER_OFFSET,
          '_handleTagListFilterOffsetRoute');

      this._mapRoute(RoutePattern.TAG_LIST_FILTER,
          '_handleTagListFilterRoute');

      this._mapRoute(RoutePattern.LEGACY_CREATE_GROUP,
          '_handleCreateGroupRoute', true);

      this._mapRoute(RoutePattern.LEGACY_CREATE_PROJECT,
          '_handleCreateProjectRoute', true);

      this._mapRoute(RoutePattern.REPO_LIST_OFFSET,
          '_handleRepoListOffsetRoute');

      this._mapRoute(RoutePattern.REPO_LIST_FILTER_OFFSET,
          '_handleRepoListFilterOffsetRoute');

      this._mapRoute(RoutePattern.REPO_LIST_FILTER,
          '_handleRepoListFilterRoute');

      this._mapRoute(RoutePattern.REPO, '_handleRepoRoute');

      this._mapRoute(RoutePattern.PLUGINS, '_handlePassThroughRoute');

      this._mapRoute(RoutePattern.PLUGIN_LIST_OFFSET,
          '_handlePluginListOffsetRoute', true);

      this._mapRoute(RoutePattern.PLUGIN_LIST_FILTER_OFFSET,
          '_handlePluginListFilterOffsetRoute', true);

      this._mapRoute(RoutePattern.PLUGIN_LIST_FILTER,
          '_handlePluginListFilterRoute', true);

      this._mapRoute(RoutePattern.PLUGIN_LIST, '_handlePluginListRoute', true);

      this._mapRoute(RoutePattern.QUERY_LEGACY_SUFFIX,
          '_handleQueryLegacySuffixRoute');

      this._mapRoute(RoutePattern.QUERY, '_handleQueryRoute');

      this._mapRoute(RoutePattern.DIFF_LEGACY_LINENUM, '_handleLegacyLinenum');

      this._mapRoute(RoutePattern.CHANGE_NUMBER_LEGACY,
          '_handleChangeNumberLegacyRoute');

      this._mapRoute(RoutePattern.DIFF_EDIT, '_handleDiffEditRoute', true);

      this._mapRoute(RoutePattern.CHANGE_EDIT, '_handleChangeEditRoute', true);

      this._mapRoute(RoutePattern.DIFF, '_handleDiffRoute');

      this._mapRoute(RoutePattern.CHANGE, '_handleChangeRoute');

      this._mapRoute(RoutePattern.CHANGE_LEGACY, '_handleChangeLegacyRoute');

      this._mapRoute(RoutePattern.DIFF_LEGACY, '_handleDiffLegacyRoute');

      this._mapRoute(RoutePattern.AGREEMENTS, '_handleAgreementsRoute', true);

      this._mapRoute(RoutePattern.NEW_AGREEMENTS, '_handleNewAgreementsRoute',
          true);

      this._mapRoute(RoutePattern.SETTINGS_LEGACY,
          '_handleSettingsLegacyRoute', true);

      this._mapRoute(RoutePattern.SETTINGS, '_handleSettingsRoute', true);

      this._mapRoute(RoutePattern.REGISTER, '_handleRegisterRoute');

      this._mapRoute(RoutePattern.LOG_IN_OR_OUT, '_handlePassThroughRoute');

      this._mapRoute(RoutePattern.IMPROPERLY_ENCODED_PLUS,
          '_handleImproperlyEncodedPlusRoute');

      this._mapRoute(RoutePattern.PLUGIN_SCREEN, '_handlePluginScreen');

      this._mapRoute(RoutePattern.DOCUMENTATION_SEARCH_FILTER,
          '_handleDocumentationSearchRoute');

      // redirects /Documentation/q/* to /Documentation/q/filter:*
      this._mapRoute(RoutePattern.DOCUMENTATION_SEARCH,
          '_handleDocumentationSearchRedirectRoute');

      // Makes sure /Documentation/* links work (doin't return 404)
      this._mapRoute(RoutePattern.DOCUMENTATION,
          '_handleDocumentationRedirectRoute');

      // Note: this route should appear last so it only catches URLs unmatched
      // by other patterns.
      this._mapRoute(RoutePattern.DEFAULT, '_handleDefaultRoute');

      page.start();
    },

    /**
     * @param {!Object} data
     * @return {Promise|null} if handling the route involves asynchrony, then a
     *     promise is returned. Otherwise, synchronous handling returns null.
     */
    _handleRootRoute(data) {
      if (data.querystring.match(/^closeAfterLogin/)) {
        // Close child window on redirect after login.
        window.close();
        return null;
      }
      let hash = this._getHashFromCanonicalPath(data.canonicalPath);
      // For backward compatibility with GWT links.
      if (hash) {
        // In certain login flows the server may redirect to a hash without
        // a leading slash, which page.js doesn't handle correctly.
        if (hash[0] !== '/') {
          hash = '/' + hash;
        }
        if (hash.includes('/ /') && data.canonicalPath.includes('/+/')) {
          // Path decodes all '+' to ' ' -- this breaks project-based URLs.
          // See Issue 6888.
          hash = hash.replace('/ /', '/+/');
        }
        const base = this.getBaseUrl();
        let newUrl = base + hash;
        if (hash.startsWith('/VE/')) {
          newUrl = base + '/settings' + hash;
        }
        this._redirect(newUrl);
        return null;
      }
      return this.$.restAPI.getLoggedIn().then(loggedIn => {
        if (loggedIn) {
          this._redirect('/dashboard/self');
        } else {
          this._redirect('/q/status:open');
        }
      });
    },

    /**
     * Decode an application/x-www-form-urlencoded string.
     *
     * @param {string} qs The application/x-www-form-urlencoded string.
     * @return {string} The decoded string.
     */
    _decodeQueryString(qs) {
      return decodeURIComponent(qs.replace(PLUS_PATTERN, ' '));
    },

    /**
     * Parse a query string (e.g. window.location.search) into an array of
     * name/value pairs.
     *
     * @param {string} qs The application/x-www-form-urlencoded query string.
     * @return {!Array<!Array<string>>} An array of name/value pairs, where each
     *     element is a 2-element array.
     */
    _parseQueryString(qs) {
      qs = qs.replace(QUESTION_PATTERN, '');
      if (!qs) {
        return [];
      }
      const params = [];
      qs.split('&').forEach(param => {
        const idx = param.indexOf('=');
        let name;
        let value;
        if (idx < 0) {
          name = this._decodeQueryString(param);
          value = '';
        } else {
          name = this._decodeQueryString(param.substring(0, idx));
          value = this._decodeQueryString(param.substring(idx + 1));
        }
        if (name) {
          params.push([name, value]);
        }
      });
      return params;
    },

    /**
     * Handle dashboard routes. These may be user, or project dashboards.
     *
     * @param {!Object} data The parsed route data.
     */
    _handleDashboardRoute(data) {
      // User dashboard. We require viewing user to be logged in, else we
      // redirect to login for self dashboard or simple owner search for
      // other user dashboard.
      return this.$.restAPI.getLoggedIn().then(loggedIn => {
        if (!loggedIn) {
          if (data.params[0].toLowerCase() === 'self') {
            this._redirectToLogin(data.canonicalPath);
          } else {
            this._redirect('/q/owner:' + encodeURIComponent(data.params[0]));
          }
        } else {
          this._setParams({
            view: Gerrit.Nav.View.DASHBOARD,
            user: data.params[0],
          });
        }
      });
    },

    /**
     * Handle custom dashboard routes.
     *
     * @param {!Object} data The parsed route data.
     * @param {string=} opt_qs Optional query string associated with the route.
     *     If not given, window.location.search is used. (Used by tests).
     */
    _handleCustomDashboardRoute(data, opt_qs) {
      // opt_qs may be provided by a test, and it may have a falsy value
      const qs = opt_qs !== undefined ? opt_qs : window.location.search;
      const queryParams = this._parseQueryString(qs);
      let title = 'Custom Dashboard';
      const titleParam = queryParams.find(
          elem => elem[0].toLowerCase() === 'title');
      if (titleParam) {
        title = titleParam[1];
      }
      // Dashboards support a foreach param which adds a base query to any
      // additional query.
      const forEachParam = queryParams.find(
          elem => elem[0].toLowerCase() === 'foreach');
      let forEachQuery = null;
      if (forEachParam) {
        forEachQuery = forEachParam[1];
      }
      const sectionParams = queryParams.filter(
          elem => elem[0] && elem[1] && elem[0].toLowerCase() !== 'title'
          && elem[0].toLowerCase() !== 'foreach');
      const sections = sectionParams.map(elem => {
        const query = forEachQuery ? `${forEachQuery} ${elem[1]}` : elem[1];
        return {
          name: elem[0],
          query,
        };
      });

      if (sections.length > 0) {
        // Custom dashboard view.
        this._setParams({
          view: Gerrit.Nav.View.DASHBOARD,
          user: 'self',
          sections,
          title,
        });
        return Promise.resolve();
      }

      // Redirect /dashboard/ -> /dashboard/self.
      this._redirect('/dashboard/self');
      return Promise.resolve();
    },

    _handleProjectDashboardRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.DASHBOARD,
        project: data.params[0],
        dashboard: decodeURIComponent(data.params[1]),
      });
    },

    _handleGroupInfoRoute(data) {
      this._redirect('/admin/groups/' + encodeURIComponent(data.params[0]));
    },

    _handleGroupSelfRedirectRoute(data) {
      this._redirect('/settings/#Groups');
    },

    _handleGroupRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.GROUP,
        groupId: data.params[0],
      });
    },

    _handleGroupAuditLogRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.GROUP,
        detail: Gerrit.Nav.GroupDetailView.LOG,
        groupId: data.params[0],
      });
    },

    _handleGroupMembersRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.GROUP,
        detail: Gerrit.Nav.GroupDetailView.MEMBERS,
        groupId: data.params[0],
      });
    },

    _handleGroupListOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-admin-group-list',
        offset: data.params[1] || 0,
        filter: null,
        openCreateModal: data.hash === 'create',
      });
    },

    _handleGroupListFilterOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-admin-group-list',
        offset: data.params.offset,
        filter: data.params.filter,
      });
    },

    _handleGroupListFilterRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-admin-group-list',
        filter: data.params.filter || null,
      });
    },

    _handleProjectsOldRoute(data) {
      let params = '';
      if (data.params[1]) {
        params = encodeURIComponent(data.params[1]);
        if (data.params[1].includes(',')) {
          params =
              encodeURIComponent(data.params[1]).replace('%2C', ',');
        }
      }

      this._redirect(`/admin/repos/${params}`);
    },

    _handleRepoCommandsRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.COMMANDS,
        repo: data.params[0],
      });
    },

    _handleRepoAccessRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.ACCESS,
        repo: data.params[0],
      });
    },

    _handleRepoDashboardsRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.DASHBOARDS,
        repo: data.params[0],
      });
    },

    _handleBranchListOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.BRANCHES,
        repo: data.params[0],
        offset: data.params[2] || 0,
        filter: null,
      });
    },

    _handleBranchListFilterOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.BRANCHES,
        repo: data.params.repo,
        offset: data.params.offset,
        filter: data.params.filter,
      });
    },

    _handleBranchListFilterRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.BRANCHES,
        repo: data.params.repo,
        filter: data.params.filter || null,
      });
    },

    _handleTagListOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.TAGS,
        repo: data.params[0],
        offset: data.params[2] || 0,
        filter: null,
      });
    },

    _handleTagListFilterOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.TAGS,
        repo: data.params.repo,
        offset: data.params.offset,
        filter: data.params.filter,
      });
    },

    _handleTagListFilterRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        detail: Gerrit.Nav.RepoDetailView.TAGS,
        repo: data.params.repo,
        filter: data.params.filter || null,
      });
    },

    _handleRepoListOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-repo-list',
        offset: data.params[1] || 0,
        filter: null,
        openCreateModal: data.hash === 'create',
      });
    },

    _handleRepoListFilterOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-repo-list',
        offset: data.params.offset,
        filter: data.params.filter,
      });
    },

    _handleRepoListFilterRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-repo-list',
        filter: data.params.filter || null,
      });
    },

    _handleCreateProjectRoute(data) {
      // Redirects the legacy route to the new route, which displays the project
      // list with a hash 'create'.
      this._redirect('/admin/repos#create');
    },

    _handleCreateGroupRoute(data) {
      // Redirects the legacy route to the new route, which displays the group
      // list with a hash 'create'.
      this._redirect('/admin/groups#create');
    },

    _handleRepoRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.REPO,
        repo: data.params[0],
      });
    },

    _handlePluginListOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-plugin-list',
        offset: data.params[1] || 0,
        filter: null,
      });
    },

    _handlePluginListFilterOffsetRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-plugin-list',
        offset: data.params.offset,
        filter: data.params.filter,
      });
    },

    _handlePluginListFilterRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-plugin-list',
        filter: data.params.filter || null,
      });
    },

    _handlePluginListRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.ADMIN,
        adminView: 'gr-plugin-list',
      });
    },

    _handleQueryRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.SEARCH,
        query: data.params[0],
        offset: data.params[2],
      });
    },

    _handleQueryLegacySuffixRoute(ctx) {
      this._redirect(ctx.path.replace(LEGACY_QUERY_SUFFIX_PATTERN, ''));
    },

    _handleChangeNumberLegacyRoute(ctx) {
      this._redirect('/c/' + encodeURIComponent(ctx.params[0]));
    },

    _handleChangeRoute(ctx) {
      // Parameter order is based on the regex group number matched.
      const params = {
        project: ctx.params[0],
        changeNum: ctx.params[1],
        basePatchNum: ctx.params[4],
        patchNum: ctx.params[6],
        view: Gerrit.Nav.View.CHANGE,
      };

      this._redirectOrNavigate(params);
    },

    _handleDiffRoute(ctx) {
      // Parameter order is based on the regex group number matched.
      const params = {
        project: ctx.params[0],
        changeNum: ctx.params[1],
        basePatchNum: ctx.params[4],
        patchNum: ctx.params[6],
        path: ctx.params[8],
        view: Gerrit.Nav.View.DIFF,
      };

      const address = this._parseLineAddress(ctx.hash);
      if (address) {
        params.leftSide = address.leftSide;
        params.lineNum = address.lineNum;
      }

      this._redirectOrNavigate(params);
    },

    _handleChangeLegacyRoute(ctx) {
      // Parameter order is based on the regex group number matched.
      const params = {
        changeNum: ctx.params[0],
        basePatchNum: ctx.params[3],
        patchNum: ctx.params[5],
        view: Gerrit.Nav.View.CHANGE,
        querystring: ctx.querystring,
      };

      this._normalizeLegacyRouteParams(params);
    },

    _handleLegacyLinenum(ctx) {
      this._redirect(ctx.path.replace(LEGACY_LINENUM_PATTERN, '#$1'));
    },

    _handleDiffLegacyRoute(ctx) {
      // Parameter order is based on the regex group number matched.
      const params = {
        changeNum: ctx.params[0],
        basePatchNum: ctx.params[2],
        patchNum: ctx.params[4],
        path: ctx.params[5],
        view: Gerrit.Nav.View.DIFF,
      };

      const address = this._parseLineAddress(ctx.hash);
      if (address) {
        params.leftSide = address.leftSide;
        params.lineNum = address.lineNum;
      }

      this._normalizeLegacyRouteParams(params);
    },

    _handleDiffEditRoute(ctx) {
      // Parameter order is based on the regex group number matched.
      this._redirectOrNavigate({
        project: ctx.params[0],
        changeNum: ctx.params[1],
        patchNum: ctx.params[2],
        path: ctx.params[3],
        view: Gerrit.Nav.View.EDIT,
      });
    },

    _handleChangeEditRoute(ctx) {
      // Parameter order is based on the regex group number matched.
      this._redirectOrNavigate({
        project: ctx.params[0],
        changeNum: ctx.params[1],
        patchNum: ctx.params[3],
        view: Gerrit.Nav.View.CHANGE,
        edit: true,
      });
    },

    /**
     * Normalize the patch range params for a the change or diff view and
     * redirect if URL upgrade is needed.
     */
    _redirectOrNavigate(params) {
      const needsRedirect = this._normalizePatchRangeParams(params);
      if (needsRedirect) {
        this._redirect(this._generateUrl(params));
      } else {
        this._setParams(params);
      }
    },

    // TODO fix this so it properly redirects
    // to /settings#Agreements (Scrolls down)
    _handleAgreementsRoute(data) {
      this._redirect('/settings/#Agreements');
    },

    _handleNewAgreementsRoute(data) {
      data.params.view = Gerrit.Nav.View.AGREEMENTS;
      this._setParams(data.params);
    },

    _handleSettingsLegacyRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.SETTINGS,
        emailToken: data.params[0],
      });
    },

    _handleSettingsRoute(data) {
      this._setParams({view: Gerrit.Nav.View.SETTINGS});
    },

    _handleRegisterRoute(ctx) {
      this._setParams({justRegistered: true});
      let path = ctx.params[0] || '/';

      // Prevent redirect looping.
      if (path.startsWith('/register')) { path = '/'; }

      if (path[0] !== '/') { return; }
      this._redirect(this.getBaseUrl() + path);
    },

    /**
     * Handler for routes that should pass through the router and not be caught
     * by the catchall _handleDefaultRoute handler.
     */
    _handlePassThroughRoute() {
      location.reload();
    },


    /**
     * URL may sometimes have /+/ encoded to / /.
     * Context: Issue 6888, Issue 7100
     */
    _handleImproperlyEncodedPlusRoute(ctx) {
      let hash = this._getHashFromCanonicalPath(ctx.canonicalPath);
      if (hash.length) { hash = '#' + hash; }
      this._redirect(`/c/${ctx.params[0]}/+/${ctx.params[1]}${hash}`);
    },

    _handlePluginScreen(ctx) {
      const view = Gerrit.Nav.View.PLUGIN_SCREEN;
      const plugin = ctx.params[0];
      const screen = ctx.params[1];
      this._setParams({view, plugin, screen});
    },

    _handleDocumentationSearchRoute(data) {
      this._setParams({
        view: Gerrit.Nav.View.DOCUMENTATION_SEARCH,
        filter: data.params.filter || null,
      });
    },

    _handleDocumentationSearchRedirectRoute(data) {
      this._redirect('/Documentation/q/filter:' +
          encodeURIComponent(data.params[0]));
    },

    _handleDocumentationRedirectRoute(data) {
      if (data.params[1]) {
        location.reload();
      } else {
        // Redirect /Documentation to /Documentation/index.html
        this._redirect('/Documentation/index.html');
      }
    },

    /**
     * Catchall route for when no other route is matched.
     */
    _handleDefaultRoute() {
      if (this._isInitialLoad) {
        // Server recognized this route as polygerrit, so we show 404.
        this._show404();
      } else {
        // Route can be recognized by server, so we pass it to server.
        this._handlePassThroughRoute();
      }
    },

    _show404() {
      // Note: the app's 404 display is tightly-coupled with catching 404
      // network responses, so we simulate a 404 response status to display it.
      // TODO: Decouple the gr-app error view from network responses.
      this._appElement().dispatchEvent(new CustomEvent('page-error',
          {detail: {response: {status: 404}}}));
    },
  });
})();
