summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authororenb <orenb@chromium.org>2015-04-10 18:25:19 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-11 01:25:47 +0000
commitf8bbca92938bf5216257f6fd64f50f41bfcb61c5 (patch)
tree9a23b54be093c9361086dd85258f59bf5f7f1d45
parent066f2b8678771a00db9402c0774e4b942001220c (diff)
downloadchromium_src-f8bbca92938bf5216257f6fd64f50f41bfcb61c5.zip
chromium_src-f8bbca92938bf5216257f6fd64f50f41bfcb61c5.tar.gz
chromium_src-f8bbca92938bf5216257f6fd64f50f41bfcb61c5.tar.bz2
Add a fork of Polymore/more-routing [1] to our settings. This approach will allow us to make local modifications in case things break in the Polymer 0.8 migration. (Main difference currently is I replaced hyphens with underscores in filenames everywhere, in line with our file name convention.)
Disabling presubmit because every warning is just related to existing JS code from the fork... we don't intend to go through and fix those. [1] https://github.com/Polymore/more-routing NOPRESUBMIT=true Review URL: https://codereview.chromium.org/1079683003 Cr-Commit-Position: refs/heads/master@{#324741}
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/MIT-LICENSE.md22
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/README.chromium16
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/driver.html2
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/driver/hash.html4
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/driver/hash_extracted.js38
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/driver/mock.html4
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/driver/mock_extracted.js19
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/driver/path.html4
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/driver/path_extracted.js32
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/driver_extracted.js107
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/more_route.html14
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/more_route_context_aware.html11
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/more_route_context_aware_extracted.js74
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/more_route_extracted.js179
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/more_route_item.html25
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/more_route_item_extracted.js63
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/more_route_selection.html13
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/more_route_selection_extracted.js168
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/more_route_selector.html20
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/more_route_selector_extracted.js134
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/more_route_switch.html19
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/more_route_switch_extracted.js84
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/more_routing.html9
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/more_routing_config.html16
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/more_routing_config_extracted.js47
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/polymer_expressions.html7
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/polymer_expressions_extracted.js40
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/route.html2
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/route_extracted.js188
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/routing.html5
-rw-r--r--chrome/browser/resources/settings/routing/more_routing/routing_extracted.js129
-rw-r--r--chrome/browser/resources/settings/routing/more_switch/more_switch.html20
-rw-r--r--chrome/browser/resources/settings/routing/more_switch/more_switch_extracted.js130
-rw-r--r--chrome/browser/resources/settings/routing/more_switch/template_switch.html24
-rw-r--r--chrome/browser/resources/settings/routing/more_switch/template_switch_extracted.js35
-rw-r--r--chrome/browser/resources/settings/settings_resources.grd87
-rwxr-xr-xtools/licenses.py2
37 files changed, 1793 insertions, 0 deletions
diff --git a/chrome/browser/resources/settings/routing/more_routing/MIT-LICENSE.md b/chrome/browser/resources/settings/routing/more_routing/MIT-LICENSE.md
new file mode 100644
index 0000000..c2e59bd
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/MIT-LICENSE.md
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+=====================
+
+Copyright (c) 2015 Ian MacLeod <ian@nevir.net>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/chrome/browser/resources/settings/routing/more_routing/README.chromium b/chrome/browser/resources/settings/routing/more_routing/README.chromium
new file mode 100644
index 0000000..32a5b30
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/README.chromium
@@ -0,0 +1,16 @@
+Name: more-routing
+Short Name: more-routing
+URL: https://github.com/Polymore/more-routing
+Version: v0.5.0
+Date: 2015-03-09
+License: MIT
+License File: MIT-LICENSE.md
+Security Critical: no
+
+Description:
+A routing library for Polymer.
+NOTE: This should no longer be needed once Polymer provides its own built-in
+routing solution.
+
+Local Modifications:
+Replace dashes with underscores and add Chromium copyright headers.
diff --git a/chrome/browser/resources/settings/routing/more_routing/driver.html b/chrome/browser/resources/settings/routing/more_routing/driver.html
new file mode 100644
index 0000000..7aea085
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/driver.html
@@ -0,0 +1,2 @@
+<html><head>
+</head><body><script charset="utf-8" src="driver_extracted.js"></script></body></html>
diff --git a/chrome/browser/resources/settings/routing/more_routing/driver/hash.html b/chrome/browser/resources/settings/routing/more_routing/driver/hash.html
new file mode 100644
index 0000000..87ea368
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/driver/hash.html
@@ -0,0 +1,4 @@
+<html><head><link rel="import" href="../driver.html">
+
+
+</head><body><script charset="utf-8" src="hash_extracted.js"></script></body></html>
diff --git a/chrome/browser/resources/settings/routing/more_routing/driver/hash_extracted.js b/chrome/browser/resources/settings/routing/more_routing/driver/hash_extracted.js
new file mode 100644
index 0000000..c5e24300
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/driver/hash_extracted.js
@@ -0,0 +1,38 @@
+// Copyright 2015 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.
+
+(function(scope) {
+var MoreRouting = scope.MoreRouting = scope.MoreRouting || {};
+MoreRouting.HashDriver = HashDriver;
+
+/**
+ * TODO(nevir): Docs.
+ */
+function HashDriver() {
+ MoreRouting.Driver.apply(this, arguments);
+ this._bindEvents();
+ this._read();
+}
+HashDriver.prototype = Object.create(MoreRouting.Driver.prototype);
+
+// By default, we prefer hashbang; but you can prefix with any string you wish.
+HashDriver.prototype.prefix = '!/';
+
+HashDriver.prototype.urlForParts = function urlForParts(parts) {
+ return '#' + MoreRouting.Driver.prototype.urlForParts.call(this, parts);
+};
+
+HashDriver.prototype.navigateToUrl = function navigateToUrl(url) {
+ window.location.hash = url;
+};
+
+HashDriver.prototype._bindEvents = function _bindEvents() {
+ window.addEventListener('hashchange', this._read.bind(this));
+};
+
+HashDriver.prototype._read = function _read() {
+ this.setCurrentPath(window.location.hash.substr(1) || this.prefix);
+};
+
+})(window);
diff --git a/chrome/browser/resources/settings/routing/more_routing/driver/mock.html b/chrome/browser/resources/settings/routing/more_routing/driver/mock.html
new file mode 100644
index 0000000..5f8f5e6
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/driver/mock.html
@@ -0,0 +1,4 @@
+<html><head><link rel="import" href="../driver.html">
+
+
+</head><body><script charset="utf-8" src="mock_extracted.js"></script></body></html>
diff --git a/chrome/browser/resources/settings/routing/more_routing/driver/mock_extracted.js b/chrome/browser/resources/settings/routing/more_routing/driver/mock_extracted.js
new file mode 100644
index 0000000..e42c1de
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/driver/mock_extracted.js
@@ -0,0 +1,19 @@
+// Copyright 2015 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.
+
+(function(scope) {
+var MoreRouting = scope.MoreRouting = scope.MoreRouting || {};
+MoreRouting.MockDriver = MockDriver;
+
+/** A mock driver for use in your tests. */
+function MockDriver() {
+ MoreRouting.Driver.apply(this, arguments);
+}
+MockDriver.prototype = Object.create(MoreRouting.Driver.prototype);
+
+MockDriver.prototype.navigateToUrl = function navigateToUrl(url) {
+ this.setCurrentPath(url);
+};
+
+})(window);
diff --git a/chrome/browser/resources/settings/routing/more_routing/driver/path.html b/chrome/browser/resources/settings/routing/more_routing/driver/path.html
new file mode 100644
index 0000000..d5bc524
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/driver/path.html
@@ -0,0 +1,4 @@
+<html><head><link rel="import" href="../driver.html">
+
+
+</head><body><script charset="utf-8" src="path_extracted.js"></script></body></html>
diff --git a/chrome/browser/resources/settings/routing/more_routing/driver/path_extracted.js b/chrome/browser/resources/settings/routing/more_routing/driver/path_extracted.js
new file mode 100644
index 0000000..87f97d3
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/driver/path_extracted.js
@@ -0,0 +1,32 @@
+// Copyright 2015 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.
+
+(function(scope) {
+var MoreRouting = scope.MoreRouting = scope.MoreRouting || {};
+MoreRouting.PathDriver = PathDriver;
+
+/**
+ * TODO(nevir): Docs.
+ */
+function PathDriver() {
+ MoreRouting.Driver.apply(this, arguments);
+ this._bindEvents();
+ this._read();
+}
+PathDriver.prototype = Object.create(MoreRouting.Driver.prototype);
+
+PathDriver.prototype.navigateToUrl = function navigateToUrl(url) {
+ window.history.pushState({}, '', url);
+ this._read();
+};
+
+PathDriver.prototype._bindEvents = function _bindEvents() {
+ window.addEventListener('popstate', this._read.bind(this));
+};
+
+PathDriver.prototype._read = function _read() {
+ this.setCurrentPath(window.location.pathname);
+};
+
+})(window);
diff --git a/chrome/browser/resources/settings/routing/more_routing/driver_extracted.js b/chrome/browser/resources/settings/routing/more_routing/driver_extracted.js
new file mode 100644
index 0000000..5754d30
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/driver_extracted.js
@@ -0,0 +1,107 @@
+// Copyright 2015 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.
+
+(function(scope) {
+var MoreRouting = scope.MoreRouting = scope.MoreRouting || {};
+MoreRouting.Driver = Driver;
+
+/**
+ * TODO(nevir): Docs.
+ */
+function Driver(opt_config) {
+ var config = opt_config || {};
+ if (config.prefix) this.prefix = config.prefix;
+
+ this._activeRoutes = [];
+
+ this._rootRoutes = [];
+}
+
+Driver.prototype.manageRoute = function manageRoute(route) {
+ route.driver = this;
+ this._appendRoute(route);
+
+ if (route.parent) {
+ if (route.parent.active) {
+ // Remember: `processPathParts` takes just the path parts relative to that
+ // route; not the full set.
+ route.processPathParts(this.currentPathParts.slice(route.parent.depth));
+ }
+ } else {
+ route.processPathParts(this.currentPathParts);
+ }
+
+ if (route.active) this._activeRoutes.push(route);
+};
+
+Driver.prototype.urlForParts = function urlForParts(parts) {
+ return this.prefix + parts.join(this.separator);
+};
+
+Driver.prototype.navigateToParts = function(parts) {
+ return this.navigateToUrl(this.urlForParts(parts));
+};
+
+Driver.prototype.navigateToUrl = function navigateToUrl(url) {
+ throw new Error(this.constructor.name + '#navigateToUrl not implemented');
+};
+
+// Subclass Interface
+
+Driver.prototype.prefix = '/';
+Driver.prototype.separator = '/';
+
+Driver.prototype.setCurrentPath = function setCurrentPath(path) {
+ this.currentPathParts = this.splitPath(path);
+ var newRoutes = this._matchingRoutes(this.currentPathParts);
+
+ // active -> inactive.
+ for (var i = 0, route; route = this._activeRoutes[i]; i++) {
+ if (newRoutes.indexOf(route) === -1) {
+ route.processPathParts(null);
+ }
+ }
+
+ this._activeRoutes = newRoutes;
+}
+
+Driver.prototype.splitPath = function splitPath(rawPath) {
+ if (this.prefix && rawPath.indexOf(this.prefix) !== 0) {
+ throw new Error(
+ 'Invalid path "' + rawPath + '"; ' +
+ 'expected it to be prefixed by "' + this.prefix + '"');
+ }
+ var path = rawPath.substr(this.prefix.length);
+ var parts = path.split(this.separator);
+ // Ignore trailing separators.
+ if (!parts[parts.length - 1]) parts.pop();
+
+ return parts;
+};
+
+// Internal Implementation
+Driver.prototype._appendRoute = function _appendRoute(route) {
+ if (route.parent) {
+ // We only care about root routes.
+ return;
+ }
+ this._rootRoutes.push(route);
+};
+
+Driver.prototype._matchingRoutes = function _matchingRoutes(parts, rootRoutes) {
+ var routes = [];
+ var candidates = rootRoutes || this._rootRoutes;
+ var route;
+ for (var i = 0; i < candidates.length; i++) {
+ route = candidates[i];
+ route.processPathParts(parts);
+ if (route.active) {
+ routes.push(route);
+ routes = routes.concat(this._matchingRoutes(parts.slice(route.compiled.length), route.children));
+ }
+ }
+ return routes;
+}
+
+})(window);
diff --git a/chrome/browser/resources/settings/routing/more_routing/more_route.html b/chrome/browser/resources/settings/routing/more_routing/more_route.html
new file mode 100644
index 0000000..68b9332
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/more_route.html
@@ -0,0 +1,14 @@
+<html><head>
+<link rel="import" href="chrome://resources/polymer/polymer/polymer.html">
+
+<link rel="import" href="routing.html">
+<link rel="import" href="more_route_context_aware.html">
+
+<!--
+TODO(nevir): Document.
+
+-->
+</head><body><polymer-element name="more-route" extends="more-route-context-aware" assetpath="">
+
+</polymer-element>
+<script charset="utf-8" src="more_route_extracted.js"></script></body></html>
diff --git a/chrome/browser/resources/settings/routing/more_routing/more_route_context_aware.html b/chrome/browser/resources/settings/routing/more_routing/more_route_context_aware.html
new file mode 100644
index 0000000..358ff4c
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/more_route_context_aware.html
@@ -0,0 +1,11 @@
+<html><head>
+<link rel="import" href="chrome://resources/polymer/polymer/polymer.html">
+<link rel="import" href="route.html">
+
+<!--
+TODO(nevir): Document.
+-->
+</head><body><polymer-element name="more-route-context-aware" assetpath="">
+
+</polymer-element>
+<script charset="utf-8" src="more_route_context_aware_extracted.js"></script></body></html>
diff --git a/chrome/browser/resources/settings/routing/more_routing/more_route_context_aware_extracted.js b/chrome/browser/resources/settings/routing/more_routing/more_route_context_aware_extracted.js
new file mode 100644
index 0000000..dc839f6
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/more_route_context_aware_extracted.js
@@ -0,0 +1,74 @@
+// Copyright 2015 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.
+
+ Polymer('more-route-context-aware', {
+
+ /** @override */
+ ready: function() {
+ // We're being stamped by a template; we need to defer until the
+ // template instance has been appended to the document.
+ if (!this.parentElement && !this.host && this.templateInstance) return;
+ this._routeContextAwareReady();
+ },
+
+ /** @override */
+ domReady: function() {
+ this._routeContextAwareReady();
+ },
+
+ /**
+ * Extension point for subclasses. They can assume that the element has
+ * been initialized by this point.
+ *
+ * If your element is to become a route context, it must define that route
+ * **synchronously** within this callback!
+ */
+ routingReady: function() {},
+
+ _routeContextAwareReady: function() {
+ if (this.routingIsReady) return;
+ this.routingIsReady = true;
+ this._awakenRouteContextAwareAncestors();
+ this.parentRoute = this._findParentRoute();
+ this.routingReady();
+ },
+
+ /**
+ * Annoyingly, `ready` doesn't appear to fire in a consistent manner
+ * between the elements that extend this. We want top-down loading of our
+ * elements so that parents can be properly built and resolved.
+ */
+ _awakenRouteContextAwareAncestors: function() {
+ var ancestors = this._findRouteContextAwareAncestors();
+ for (var i = 0, ancestor; ancestor = ancestors[i]; i++) {
+ ancestor._routeContextAwareReady();
+ }
+ },
+
+ _findParentRoute: function() {
+ var node = this;
+ while (node) {
+ node = node.parentNode || node.host;
+ var route = node && (node.moreRouteContext || node.route);
+ if (route instanceof MoreRouting.Route) {
+ return route;
+ }
+ }
+ return null;
+ },
+
+ _findRouteContextAwareAncestors: function() {
+ var node = this;
+ var ancestors = [];
+ while (node) {
+ node = node.parentNode || node.host;
+ if (node && node._routeContextAwareReady) {
+ ancestors.push(node);
+ }
+ }
+ return ancestors;
+ }
+
+ });
+
diff --git a/chrome/browser/resources/settings/routing/more_routing/more_route_extracted.js b/chrome/browser/resources/settings/routing/more_routing/more_route_extracted.js
new file mode 100644
index 0000000..53afa3f
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/more_route_extracted.js
@@ -0,0 +1,179 @@
+// Copyright 2015 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.
+
+ Polymer('more-route', {
+ publish: {
+ /**
+ * The name of this route. Behavior differs based on the presence of
+ * `path` during _declaration_.
+ *
+ * If `path` is present during declaration, it is registered via `name`.
+ *
+ * Otherwise, this `more-route` becomes a `reference` to the route with
+ * `name`. Changing `name` will update which route is referenced.
+ *
+ * @attribute name
+ * @type String
+ */
+ name: '',
+
+ /**
+ * A path expression used to parse parameters from the window's URL.
+ *
+ * @attribute path
+ * @type String
+ */
+ path: '',
+
+ /**
+ * Whether this route should become a context for the element that
+ * contains it.
+ *
+ * @attribute context
+ * @type Boolean
+ * @default false
+ */
+ context: false,
+
+ /**
+ * The full path expression for this route, including routes this is
+ * nested within.
+ *
+ * @attribute fullPath
+ * @type String
+ * @readonly
+ */
+ fullPath: '',
+
+ /**
+ * Whether this route is a reference to a named route.
+ *
+ * @attribute reference
+ * @type Boolean
+ */
+ reference: false,
+
+ /**
+ * Param values matching the current URL, or an empty object if not
+ * `active`.
+ *
+ * @attribute params
+ * @type Object
+ */
+ params: {},
+
+ /**
+ * Whether the route matches the current URL.
+ *
+ * @attribute active
+ * @type Boolean
+ * @readonly
+ */
+ active: false,
+
+ /**
+ * The underlying `MoreRouting.Route` object that is being wrapped.
+ *
+ * @attribute route
+ * @type MoreRouting.Route
+ * @readonly
+ */
+ route: null,
+
+ /**
+ * The parent `more-route` element, if it is nested within another.
+ *
+ * Parents are found by searching up this element's ancestry for nodes
+ * that are `more-route` elements, or have a `moreRouteContext`
+ * property.
+ *
+ * @attribute parent
+ * @type <more-route>
+ * @readonly
+ */
+ parent: null,
+ },
+
+ observe: {
+ 'name': '_identityChanged',
+ 'path': '_identityChanged',
+ 'reference': '_identityChanged',
+ // TODO(nevir): Truly read-only properties would be super handy.
+ 'active': '_updateProxiedValues',
+ },
+
+ /** @override */
+ routingReady: function() {
+ this.reference = this.name && !this.path;
+ this._identityChangedCallCount = 0;
+ this._identityChanged();
+ },
+
+ urlFor: function(params) {
+ return this.route.urlFor(params);
+ },
+
+ navigateTo: function(params) {
+ return this.route.navigateTo(params);
+ },
+
+ isCurrentUrl: function(params) {
+ return this.route.isCurrentUrl(params);
+ },
+
+ _identityChanged: function() {
+ if (!this.routingIsReady) return;
+
+ this._identityChangedCallCount = this._identityChangedCallCount + 1;
+ if (this._identityChangedCallCount === 2) return;
+
+ if (this.name && this.reference) {
+ this.route = MoreRouting.getRouteByName(this.name);
+ } else if (this.path && this.name) {
+ this.route = MoreRouting.registerNamedRoute(this.name, this.path, this.parentRoute);
+ } else if (this.path) {
+ this.route = MoreRouting.getRouteByPath(this.path, this.parentRoute);
+ } else {
+ this.route = null;
+ }
+
+ if (this._routeObserver) this._routeObserver.close();
+ if (this.route) {
+ this.params = this.route.params;
+ this.path = this.route.path;
+ this.fullPath = this.route.fullPath;
+ this._observeRoute(this.route);
+ } else {
+ this.params = {};
+ this.path = '';
+ this.fullPath = '';
+ }
+
+ if (this.hasAttribute('context')) {
+ var parent = this.parentElement || this.parentNode && this.parentNode.host;
+ if (!parent) {
+ console.warn(this, 'wants to create a routing context, but it has no parent');
+ return;
+ }
+ parent.moreRouteContext = this.route;
+ }
+ },
+
+ _updateProxiedValues: function() {
+ var previousActive = this.active;
+ this.active = this.route && this.route.active;
+
+ if (this.active === previousActive) return;
+ var eventName = 'more-route-' + (this.active ? 'active' : 'inactive');
+ this.fire(eventName, this.route);
+ },
+
+ _observeRoute: function(route) {
+ this._routeObserver = new CompoundObserver();
+ this._routeObserver.addPath(route, 'active');
+ this._routeObserver.open(this._updateProxiedValues.bind(this));
+ },
+
+ });
+
diff --git a/chrome/browser/resources/settings/routing/more_routing/more_route_item.html b/chrome/browser/resources/settings/routing/more_routing/more_route_item.html
new file mode 100644
index 0000000..57fae83
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/more_route_item.html
@@ -0,0 +1,25 @@
+<html><head>
+<link rel="import" href="chrome://resources/polymer/polymer/polymer.html">
+<link rel="import" href="chrome://resources/polymer/core-item/core-item.html">
+
+<link rel="import" href="more_route.html">
+
+<!--
+
+-->
+</head><body><polymer-element name="more-route-item" extends="core-item" on-tap="{{_onTap}}" assetpath="">
+ <template>
+ <shadow></shadow>
+
+ <style>
+ :host {
+ cursor: pointer;
+ }
+ </style>
+
+ <more-route id="route" name="{{name}}" path="{{path}}"></more-route>
+ </template>
+
+
+</polymer-element>
+<script charset="utf-8" src="more_route_item_extracted.js"></script></body></html>
diff --git a/chrome/browser/resources/settings/routing/more_routing/more_route_item_extracted.js b/chrome/browser/resources/settings/routing/more_routing/more_route_item_extracted.js
new file mode 100644
index 0000000..494233b
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/more_route_item_extracted.js
@@ -0,0 +1,63 @@
+// Copyright 2015 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.
+
+ Polymer('more-route-item', {
+ publish: {
+ /**
+ * The name of this route.
+ *
+ * @attribute name
+ * @type String
+ */
+ name: '',
+
+ /**
+ * A path expression used to parse parameters from the window's URL.
+ *
+ * @attribute path
+ * @type String
+ */
+ path: '',
+
+ /**
+ * Param values to use for navigating to this item, and for determining
+ * whether the item is `current`.
+ *
+ * @attribute params
+ * @type Object
+ */
+ params: {},
+
+ /**
+ * Whether the route matches the current URL.
+ *
+ * @attribute active
+ * @type Boolean
+ * @readonly
+ */
+ active: {value: false, reflect: true},
+
+ /**
+ * Whether the route _and params_ match the current URL.
+ *
+ * @attribute current
+ * @type Boolean
+ * @readonly
+ */
+ current: {value: false, reflect: true},
+ },
+
+ observe: {
+ '$.route.route.parts': '_updateCurrent',
+ },
+
+ _updateCurrent: function() {
+ this.current = this.$.route.isCurrentUrl(this.params);
+ },
+
+ _onTap: function() {
+ this.$.route.navigateTo(this.params);
+ },
+ });
+
diff --git a/chrome/browser/resources/settings/routing/more_routing/more_route_selection.html b/chrome/browser/resources/settings/routing/more_routing/more_route_selection.html
new file mode 100644
index 0000000..d78aca1
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/more_route_selection.html
@@ -0,0 +1,13 @@
+<html><head>
+<link rel="import" href="chrome://resources/polymer/polymer/polymer.html">
+
+<link rel="import" href="more_route_context_aware.html">
+<link rel="import" href="route.html">
+
+<!--
+TODO(nevir): Document.
+-->
+</head><body><polymer-element name="more-route-selection" extends="more-route-context-aware" assetpath="">
+
+</polymer-element>
+<script charset="utf-8" src="more_route_selection_extracted.js"></script></body></html>
diff --git a/chrome/browser/resources/settings/routing/more_routing/more_route_selection_extracted.js b/chrome/browser/resources/settings/routing/more_routing/more_route_selection_extracted.js
new file mode 100644
index 0000000..a7669ce
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/more_route_selection_extracted.js
@@ -0,0 +1,168 @@
+// Copyright 2015 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.
+
+ Polymer('more-route-selection', {
+ publish: {
+ /**
+ * Routes to select from, as either a path expression or route name.
+ *
+ * You can either specify routes via this attribute, or as child nodes
+ * to this element, but not both.
+ *
+ * @attribute routes
+ * @type Array<string|MoreRouting.Route>
+ */
+ routes: [],
+
+ /**
+ * The index of the selected route (relative to `routes`). -1 when there
+ * is no active route.
+ *
+ * @attribute selectedIndex
+ * @type integer
+ * @readonly
+ */
+ selectedIndex: -1,
+
+ /**
+ * The selected `MoreRouting.Route` object, or `null`.
+ *
+ * @attribute selectedRoute
+ * @type MoreRouting.Route
+ * @readonly
+ */
+ selectedRoute: null,
+
+ /**
+ * The path expression of the selected route, or `null` if no route.
+ *
+ * @attribute selectedPath
+ * @type ?string
+ * @readonly
+ */
+ selectedPath: null,
+
+ /**
+ * The params of the selected route, or an empty object if no route.
+ *
+ * @attribute selectedParams
+ * @type Object
+ * @readonly
+ */
+ selectedParams: {},
+ },
+
+ /**
+ * @event more-route-change fires when a new route is selected.
+ * @param {{
+ * newRoute: MoreRouting.Route, oldRoute: MoreRouting.Route,
+ * newIndex: number, oldIndex: number,
+ * newPath: ?string, oldPath: ?string,
+ * newParams: Object, oldParams: Object,
+ * }}
+ */
+
+ /** @override */
+ routingReady: function() {
+ this.routesChanged();
+ },
+
+ routesChanged: function() {
+ if (!this.routingIsReady) return;
+
+ this._routeInfo = this._sortIndexes(this.routes.map(function(route, index) {
+ return {
+ model: MoreRouting.getRoute(route, this.parentRoute),
+ index: index,
+ };
+ }.bind(this)));
+
+ this._observeRoutes();
+ this._evaluate();
+ },
+
+ /**
+ * Tracks changes to the routes.
+ *
+ * TODO(nevir): Consider having a global 'route-changed' event so we're
+ * just observing one object (MoreRouting.driver.currentPathParts?).
+ */
+ _observeRoutes: function() {
+ if (this._observer) {
+ this._observer.close();
+ }
+ this._observer = new CompoundObserver();
+ for (var i = 0, routeInfo; routeInfo = this._routeInfo[i]; i++) {
+ this._observer.addPath(routeInfo.model, 'active');
+ }
+ this._observer.open(this._evaluate.bind(this));
+ },
+
+ _evaluate: function() {
+ var newIndex = -1;
+ var newRoute = null;
+ var oldIndex = this.selectedIndex;
+
+ for (var i = 0, routeInfo; routeInfo = this._routeInfo[i]; i++) {
+ if (routeInfo.model && routeInfo.model.active) {
+ newIndex = routeInfo.index;
+ newRoute = routeInfo.model;
+ break;
+ }
+ }
+ if (newIndex === oldIndex) return;
+
+ var oldRoute = this.selectedRoute;
+ var oldPath = this.selectedPath;
+ var oldParams = this.selectedParams;
+
+ var newPath = newRoute ? newRoute.path : null;
+ var newParams = newRoute ? newRoute.params : {};
+
+ this.selectedRoute = newRoute;
+ this.selectedIndex = newIndex;
+ this.selectedPath = newPath;
+ this.selectedParams = newParams;
+
+ this.fire('more-route-change', {
+ newRoute: newRoute, oldRoute: oldRoute,
+ newIndex: newIndex, oldIndex: oldIndex,
+ newPath: newPath, oldPath: oldPath,
+ newParams: newParams, oldParams: oldParams,
+ });
+ },
+ /**
+ * We want the most specific routes to match first, so we must create a
+ * mapping of indexes within `routes` that map
+ */
+ _sortIndexes: function(routeInfo) {
+ return routeInfo.sort(function(a, b) {
+ if (!a.model) {
+ return 1;
+ } else if (!b.model) {
+ return -1;
+ // Routes with more path parts are most definitely more specific.
+ } else if (a.model.depth < b.model.depth) {
+ return 1;
+ } if (a.model.depth > b.model.depth) {
+ return -1;
+ } else {
+
+ // Also, routes with fewer params are more specific. For example
+ // `/users/foo` is more specific than `/users/:id`.
+ if (a.model.numParams < b.model.numParams) {
+ return -1;
+ } else if (a.model.numParams > b.model.numParams) {
+ return 1;
+ } else {
+ // Equally specific; we fall back to the default (and hopefully
+ // stable) sort order.
+ return 0;
+ }
+ }
+ });
+ },
+
+ });
+
diff --git a/chrome/browser/resources/settings/routing/more_routing/more_route_selector.html b/chrome/browser/resources/settings/routing/more_routing/more_route_selector.html
new file mode 100644
index 0000000..4261679
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/more_route_selector.html
@@ -0,0 +1,20 @@
+<html><head>
+<link rel="import" href="chrome://resources/polymer/polymer/polymer.html">
+
+<link rel="import" href="more_route_context_aware.html">
+<link rel="import" href="more_route_selection.html">
+
+<!--
+TODO(nevir): Document.
+
+TODO(nevir): Support child addition/removal/reorder.
+-->
+</head><body><polymer-element name="more-route-selector" extends="more-route-context-aware" assetpath="">
+ <template>
+ <more-route-selection id="selection" selectedindex="{{selectedIndex}}" selectedroute="{{selectedRoute}}" selectedpath="{{selectedPath}}" selectedparams="{{selectedParams}}">
+ </more-route-selection>
+ <content></content>
+ </template>
+
+</polymer-element>
+<script charset="utf-8" src="more_route_selector_extracted.js"></script></body></html>
diff --git a/chrome/browser/resources/settings/routing/more_routing/more_route_selector_extracted.js b/chrome/browser/resources/settings/routing/more_routing/more_route_selector_extracted.js
new file mode 100644
index 0000000..a8508ab
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/more_route_selector_extracted.js
@@ -0,0 +1,134 @@
+// Copyright 2015 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.
+
+ Polymer('more-route-selector', {
+ publish: {
+ /**
+ * The attribute to read route expressions from (on children).
+ *
+ * @attribute routeAttribute
+ * @type String
+ */
+ routeAttribute: 'route',
+
+ /**
+ * The index of the selected route (relative to `routes`). -1 when there
+ * is no active route.
+ *
+ * @attribute selectedIndex
+ * @type integer
+ * @readonly
+ */
+ selectedIndex: -1,
+
+ /**
+ * The selected `MoreRouting.Route` object, or `null`.
+ *
+ * @attribute selectedRoute
+ * @type MoreRouting.Route
+ * @readonly
+ */
+ selectedRoute: null,
+
+ /**
+ * The path expression of the selected route, or `null` if no route.
+ *
+ * @attribute selectedPath
+ * @type ?string
+ * @readonly
+ */
+ selectedPath: null,
+
+ /**
+ * The params of the selected route, or an empty object if no route.
+ *
+ * @attribute selectedParams
+ * @type Object
+ * @readonly
+ */
+ selectedParams: {},
+ },
+
+ /**
+ * @event more-route-selected fires when a new route is selected.
+ * @param {{
+ * newRoute: MoreRouting.Route, oldRoute: MoreRouting.Route,
+ * newIndex: number, oldIndex: number,
+ * newPath: ?string, oldPath: ?string,
+ * newParams: Object, oldParams: Object,
+ * }}
+ */
+
+ /** @override */
+ domReady: function() {
+ this.super();
+ // Rather than performing this setup in `routingReady`, we defer until
+ // domReady so that our children have a chance to set up.
+ this._managedSelector = this._findChildSelector();
+ // `routingReady` fires top-down; we need to let them do their thing
+ // before we walk them.
+ this.async(function() {
+ this.$.selection.routes = this._routesFromChildren();
+ this._observeManagedSelector();
+ });
+ },
+
+ selectedIndexChanged: function() {
+ if (!this.routingIsReady || !this._managedSelector) return;
+ this._managedSelector.selected = this.selectedIndex;
+ },
+
+ /**
+ * Are we managing a `core-selector`?
+ */
+ _findChildSelector: function() {
+ if (this.children.length !== 1) return null;
+ var child = this.firstElementChild;
+ if ('selected' in child && 'items' in child) { // Quack!
+ return child;
+ }
+ },
+
+ _observeManagedSelector: function() {
+ if (!this._managedSelector) return;
+
+ this._observer = new PathObserver(this._managedSelector, 'selectedIndex');
+ this._observer.open(function(newIndex) {
+ if (this.selectedIndex === this._managedSelector.selectedIndex) return;
+ var route = this.$.selection.routes[newIndex];
+ if (!route) return;
+ route.navigateTo();
+ }.bind(this));
+ },
+
+ _routesFromChildren: function() {
+ // If we aren't managing a `core-selector`, just use our own children.
+ var context = this._managedSelector || this;
+ var routes = [];
+ for (var i = 0, child; child = context.children[i]; i++) {
+ routes.push(this._routeForChild(child));
+ }
+
+ return routes;
+ },
+
+ _routeForChild: function(child) {
+ if (child.moreRouteContext && child.moreRouteContext instanceof MoreRouting.Route) {
+ return child.moreRouteContext;
+ }
+
+ if (!child.hasAttribute(this.routeAttribute)) {
+ console.warn('Child of', this, 'is missing route attribute "' + this.routeAttribute + '":', child);
+ return null;
+ }
+ var expression = child.getAttribute(this.routeAttribute);
+ var route = MoreRouting.getRoute(expression, this.parentRoute);
+ // Associate the route w/ its element while we're here.
+ child.moreRouteContext = route;
+
+ return route;
+ },
+
+ });
+
diff --git a/chrome/browser/resources/settings/routing/more_routing/more_route_switch.html b/chrome/browser/resources/settings/routing/more_routing/more_route_switch.html
new file mode 100644
index 0000000..ec3aa46
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/more_route_switch.html
@@ -0,0 +1,19 @@
+<html><head>
+<link rel="import" href="chrome://resources/polymer/polymer/polymer.html">
+<link rel="import" href="../more_switch/template_switch.html">
+
+<link rel="import" href="more_route.html">
+<link rel="import" href="routing.html">
+
+<!--
+
+-->
+</head><body><polymer-element name="more-route-switch" extends="template-switch" assetpath="">
+ <template>
+ <shadow></shadow>
+ <more-route id="activeRouteEl"></more-route>
+ </template>
+
+
+</polymer-element>
+<script charset="utf-8" src="more_route_switch_extracted.js"></script></body></html>
diff --git a/chrome/browser/resources/settings/routing/more_routing/more_route_switch_extracted.js b/chrome/browser/resources/settings/routing/more_routing/more_route_switch_extracted.js
new file mode 100644
index 0000000..27a6cac
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/more_route_switch_extracted.js
@@ -0,0 +1,84 @@
+// Copyright 2015 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.
+
+ Polymer('more-route-switch', {
+ publish: {
+ routeContext: false,
+ activeRoute: null,
+ paramsProperty: 'params',
+ },
+
+ ready: function() {
+ if (this.routeContext) {
+ this.moreRouteContext = this.$.activeRouteEl;
+ }
+ },
+
+ attached: function() {
+ // We need to defer attaching until the DOM has fully resolved, so that
+ // any parent routes are discovered.
+ this.async(function() {
+ this.observeChildren();
+ this.evaluate();
+ });
+ },
+
+ /** @override */
+ observeChildren: function() {
+ this._observer = new CompoundObserver();
+ for (var i = 0, child; child = this.children[i]; i++) {
+ this._observer.addPath(this._routeForChild(child), 'active');
+ }
+ this._observer.open(this.evaluate.bind(this));
+ },
+
+ /** @override */
+ childIsTruthy: function(child, index) {
+ return this._routeForChild(child).active;
+ },
+
+ /** @override */
+ activateChild: function(child, index, external) {
+ this.super(arguments);
+ if (!child) {
+ this.activeRoute = null;
+ return;
+ }
+ this.activeRoute = this._routeForChild(child);
+ this.$.activeRouteEl.path = this.activeRoute.path;
+
+ if (!external) return;
+ this.activeRoute.navigateTo(this._paramsForChild(child));
+ },
+
+ /** @override */
+ modelForChild: function(child, index) {
+ var model = Object.create(this.super(arguments));
+ model[this.paramsProperty] = this._paramsForChild(child);
+ return model;
+ },
+
+ _paramsForChild: function(child) {
+ var route = this._routeForChild(child);
+ return route && route.active ? route.params : this._parentParams;
+ },
+
+ get _parentParams() {
+ return this.$.activeRouteEl.parent && this.$.activeRouteEl.parent.params || {};
+ },
+
+ _routeForChild: function(child) {
+ var pathOrName = child.getAttribute('when-route') || '/';
+ if (!MoreRouting.isPath(pathOrName)) {
+ return MoreRouting.getRouteByName(pathOrName);
+ }
+
+ var path = pathOrName;
+ if (this.$.activeRouteEl.parent) {
+ path = MoreRouting.joinPath(this.$.activeRouteEl.parent.path, path);
+ }
+ return MoreRouting.getRouteByPath(path);
+ },
+ });
+
diff --git a/chrome/browser/resources/settings/routing/more_routing/more_routing.html b/chrome/browser/resources/settings/routing/more_routing/more_routing.html
new file mode 100644
index 0000000..06029a4
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/more_routing.html
@@ -0,0 +1,9 @@
+<!--
+The order matters here! Elements are upgraded first by registration order, THEN
+by DOM order.
+-->
+<link rel="import" href="more_routing_config.html">
+<link rel="import" href="polymer_expressions.html">
+<link rel="import" href="routing.html">
+<link rel="import" href="more_route.html">
+<link rel="import" href="more_route_selector.html">
diff --git a/chrome/browser/resources/settings/routing/more_routing/more_routing_config.html b/chrome/browser/resources/settings/routing/more_routing/more_routing_config.html
new file mode 100644
index 0000000..7ded399
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/more_routing_config.html
@@ -0,0 +1,16 @@
+<html><head>
+<link rel="import" href="chrome://resources/polymer/polymer/polymer.html">
+
+<link rel="import" href="routing.html">
+<!-- TODO(nevir): import on demand? -->
+<link rel="import" href="driver/hash.html">
+<link rel="import" href="driver/mock.html">
+<link rel="import" href="driver/path.html">
+
+<!--
+TODO(nevir): Document.
+-->
+</head><body><polymer-element name="more-routing-config" assetpath="">
+
+</polymer-element>
+<script charset="utf-8" src="more_routing_config_extracted.js"></script></body></html>
diff --git a/chrome/browser/resources/settings/routing/more_routing/more_routing_config_extracted.js b/chrome/browser/resources/settings/routing/more_routing/more_routing_config_extracted.js
new file mode 100644
index 0000000..a8e86d3
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/more_routing_config_extracted.js
@@ -0,0 +1,47 @@
+// Copyright 2015 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.
+
+ Polymer('more-routing-config', {
+ publish: {
+ /**
+ * The routing driver to use.
+ *
+ * * `hash`: `MoreRouting.HashDriver`
+ * * `path`: `MoreRouting.PathDriver`
+ * * `mock`: `MoreRouting.MockDriver`
+ *
+ * @attribute driver
+ * @type String
+ */
+ driver: '',
+
+ /**
+ *
+ */
+ urlPrefix: '',
+ },
+
+ ready: function() {
+ var driver;
+ // TODO(nevir): Support custom drivers, too.
+ if (this.driver === 'hash') {
+ driver = new MoreRouting.HashDriver(this._config);
+ } else if (this.driver === 'path') {
+ driver = new MoreRouting.PathDriver(this._config);
+ } else if (this.driver === 'mock') {
+ driver = new MoreRouting.MockDriver(this._config);
+ } else {
+ throw new Error('Unknown driver type "' + this.driver + '"');
+ }
+
+ MoreRouting.driver = driver;
+ },
+
+ get _config() {
+ var config = {};
+ if (this.urlPrefix) config.prefix = this.urlPrefix;
+ return config;
+ },
+ });
+
diff --git a/chrome/browser/resources/settings/routing/more_routing/polymer_expressions.html b/chrome/browser/resources/settings/routing/more_routing/polymer_expressions.html
new file mode 100644
index 0000000..902806b
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/polymer_expressions.html
@@ -0,0 +1,7 @@
+<html><head>
+<link rel="import" href="chrome://resources/polymer/polymer/polymer.html">
+
+<link rel="import" href="routing.html">
+
+
+</head><body><script charset="utf-8" src="polymer_expressions_extracted.js"></script></body></html>
diff --git a/chrome/browser/resources/settings/routing/more_routing/polymer_expressions_extracted.js b/chrome/browser/resources/settings/routing/more_routing/polymer_expressions_extracted.js
new file mode 100644
index 0000000..aecc6a7
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/polymer_expressions_extracted.js
@@ -0,0 +1,40 @@
+// Copyright 2015 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.
+
+(function(scope) {
+var PolymerExpressions = scope.PolymerExpressions;
+var MoreRouting = scope.MoreRouting = scope.MoreRouting || {};
+
+/**
+ *
+ */
+PolymerExpressions.prototype.route = function route(pathOrName) {
+ return MoreRouting.getRoute(pathOrName);
+};
+
+/**
+ *
+ */
+PolymerExpressions.prototype.urlFor = function urlFor(pathOrName, params) {
+ return MoreRouting.urlFor(pathOrName, params);
+};
+
+/**
+ * Determines whether the current URL matches a route _and specific params_.
+ *
+ * @param {string} pathOrName
+ * @param {!Object} params
+ * @return {boolean} Whether the route found via `pathOrName` is active, and
+ * `params` matches its current params.
+ */
+PolymerExpressions.prototype.isCurrentUrl = {
+ filter: function isCurrentUrl(pathOrName, params) {
+ return MoreRouting.getRoute(pathOrName).isCurrentUrl(params);
+ },
+ extraDeps: function isCurrentUrlExtraDeps(pathOrName, params) {
+ // TODO(nevir): Why does this only trigger once if we return a PathObserver?
+ return [[MoreRouting.getRoute(pathOrName), 'parts']];
+ },
+};
+})(window);
diff --git a/chrome/browser/resources/settings/routing/more_routing/route.html b/chrome/browser/resources/settings/routing/more_routing/route.html
new file mode 100644
index 0000000..dc9df29
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/route.html
@@ -0,0 +1,2 @@
+<html><head>
+</head><body><script charset="utf-8" src="route_extracted.js"></script></body></html>
diff --git a/chrome/browser/resources/settings/routing/more_routing/route_extracted.js b/chrome/browser/resources/settings/routing/more_routing/route_extracted.js
new file mode 100644
index 0000000..c339cbd
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/route_extracted.js
@@ -0,0 +1,188 @@
+// Copyright 2015 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.
+
+(function(scope) {
+var MoreRouting = scope.MoreRouting = scope.MoreRouting || {};
+MoreRouting.Route = Route;
+
+// Note that this can differ from the part separator defined by the driver. The
+// driver's separator is used when parsing/generating URLs given to the client,
+// whereas this one is for route definitions.
+var PART_SEPARATOR = '/';
+var PARAM_SENTINEL = ':';
+var SEPARATOR_CLEANER = /\/\/+/g;
+
+/**
+ * TODO(nevir): Docs.
+ */
+function Route(path, parent) {
+ this.path = path;
+ this.parent = parent;
+ this.fullPath = path;
+ this.compiled = this._compile(this.path);
+ this.active = false;
+ this.driver = null;
+
+ this.parts = [];
+ this.children = [];
+
+ /**
+ * Param values matching the current URL, or an empty object if not `active`.
+ *
+ * To make data "binding" easy, `Route` guarantees that `params` will always
+ * be the same object; just make a reference to it.
+ */
+ if (this.parent) {
+ this.params = Object.create(this.parent.params);
+ this.parent.children.push(this);
+ this.fullPath = this.parent.fullPath + this.fullPath;
+ this.depth = this.parent.depth + this.compiled.length;
+ this.numParams = this.parent.numParams + countParams(this.compiled);
+ } else {
+ this.params = {};
+ this.depth = this.compiled.length;
+ this.numParams = countParams(this.compiled);
+ }
+
+ this._paramObserver = new ObjectObserver(this.params);
+ this._paramObserver.open(this._navigateToParams.bind(this));
+}
+
+Route.isPath = function isPath(pathOrName) {
+ return pathOrName.indexOf(PART_SEPARATOR) === 0;
+};
+
+Route.joinPath = function joinPath(paths) {
+ var joined = Array.prototype.join.call(arguments, PART_SEPARATOR);
+ joined = joined.replace(SEPARATOR_CLEANER, PART_SEPARATOR);
+
+ var minLength = joined.length - PART_SEPARATOR.length;
+ if (joined.substr(minLength) === PART_SEPARATOR) {
+ joined = joined.substr(0, minLength);
+ }
+
+ return joined;
+};
+
+Route.prototype.urlFor = function urlFor(params) {
+ return this.driver.urlForParts(this.partsForParams(params));
+};
+
+Route.prototype.navigateTo = function navigateTo(params) {
+ return this.driver.navigateToParts(this.partsForParams(params));
+}
+
+Route.prototype.isCurrentUrl = function isCurrentUrl(params) {
+ if (!this.active) return false;
+ var currentKeys = Object.keys(this.params);
+ for (var i = 0, key; key = currentKeys[i]; i++) {
+ if (this.params[key] !== String(params[key])) {
+ return false;
+ }
+ }
+ return true;
+};
+
+// Driver Interface
+
+Route.prototype.partsForParams = function partsForParams(params, silent) {
+ var parts = this.parent && this.parent.partsForParams(params, silent) || [];
+ for (var i = 0, config; config = this.compiled[i]; i++) {
+ if (config.type === 'static') {
+ parts.push(config.part);
+ } else if (config.type === 'param') {
+ var value
+ if (params && config.name in params) {
+ value = params[config.name];
+ } else {
+ value = this.params[config.name] || this.params.prototype[config.name];
+ }
+ if (value === undefined) {
+ if (silent) {
+ return null;
+ } else {
+ throw new Error('Missing param "' + config.name + '" for route ' + this);
+ }
+ }
+ parts.push(value);
+ }
+ }
+ return parts;
+};
+
+/**
+ * Called by the driver whenever it has detected a change to the URL.
+ *
+ * @param {Array.<String>|null} parts The parts of the URL, or null if the
+ * route should be disabled.
+ */
+Route.prototype.processPathParts = function processPathParts(parts) {
+ this.parts = parts;
+ this.active = this.matchesPathParts(parts);
+ if (this.active) {
+ var keys = Object.keys(this.params);
+ for (var i = 0; i < keys.length; i++) {
+ delete this.params[keys[i]];
+ }
+ for (var i = 0, config; config = this.compiled[i]; i++) {
+ if (config.type === 'param') {
+ this.params[config.name] = parts[i];
+ }
+ }
+ } else {
+ for (key in this.params) {
+ this.params[key] = undefined;
+ }
+ }
+ this._paramObserver.discardChanges();
+};
+
+Route.prototype.matchesPathParts = function matchesPathParts(parts) {
+ if (!parts) return false;
+ if (parts.length < this.compiled.length) return false;
+ for (var i = 0, config; config = this.compiled[i]; i++) {
+ if (config.type === 'static' && parts[i] !== config.part) {
+ return false;
+ }
+ }
+ return true;
+};
+
+Route.prototype.toString = function toString() {
+ return this.path;
+};
+
+// Internal Implementation
+
+Route.prototype._compile = function _compile(rawPath) {
+ // Not strictly required, but helps us stay consistent w/ `getRoute`, etc.
+ if (rawPath.indexOf(PART_SEPARATOR) !== 0) {
+ throw new Error('Route paths must begin with a path separator; got: "' + rawPath + '"');
+ }
+ var path = rawPath.substr(PART_SEPARATOR.length);
+ if (path === '') return [];
+
+ return path.split(PART_SEPARATOR).map(function(part) {
+ // raw fragment.
+ if (part.substr(0, 1) == PARAM_SENTINEL) {
+ return {type: 'param', name: part.substr(1)};
+ } else {
+ return {type: 'static', part: part};
+ }
+ });
+};
+
+Route.prototype._navigateToParams = function _navigateToParams() {
+ var parts = this.partsForParams(this.params, true);
+ if (!parts) return;
+ this.driver.navigateToParts(parts);
+};
+
+function countParams(compiled) {
+ return compiled.reduce(function(count, part) {
+ return count + (part.type === 'param' ? 1 : 0);
+ }, 0);
+}
+
+})(window);
diff --git a/chrome/browser/resources/settings/routing/more_routing/routing.html b/chrome/browser/resources/settings/routing/more_routing/routing.html
new file mode 100644
index 0000000..44a6e10
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/routing.html
@@ -0,0 +1,5 @@
+<html><head><link rel="import" href="polymer_expressions.html">
+<link rel="import" href="route.html">
+
+
+</head><body><script charset="utf-8" src="routing_extracted.js"></script></body></html>
diff --git a/chrome/browser/resources/settings/routing/more_routing/routing_extracted.js b/chrome/browser/resources/settings/routing/more_routing/routing_extracted.js
new file mode 100644
index 0000000..58734cf
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_routing/routing_extracted.js
@@ -0,0 +1,129 @@
+// Copyright 2015 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.
+
+(function(scope) {
+var MoreRouting = scope.MoreRouting = scope.MoreRouting || {};
+
+// Route singletons.
+var routesByPath = {};
+var pathsByName = {};
+
+// Route Management
+
+/**
+ * Retrieves (or builds) the singleton `Route` for the given path expression or
+ * route name.
+ *
+ * Paths begin with `/`; anything else is considered a name.
+ *
+ * For convenience, `Route` objects can also be passed (and will be returned) -
+ * this can be used as a route coercion function.
+ *
+ * @param {String|MoreRouting.Route} pathOrName
+ * @param {MoreRouting.Route} parent
+ * @return {MoreRouting.Route}
+ */
+MoreRouting.getRoute = function getRoute(pathOrName, parent) {
+ if (typeof pathOrName !== 'string') return pathOrName;
+ if (this.isPath(pathOrName)) {
+ return this.getRouteByPath(pathOrName, parent);
+ } else {
+ return this.getRouteByName(pathOrName);
+ }
+}
+
+/**
+ * Retrieves (or builds) the singleton `Route` for the given path expression.
+ *
+ * @param {String} path
+ * @param {MoreRouting.Route} parent
+ * @return {MoreRouting.Route}
+ */
+MoreRouting.getRouteByPath = function getRouteByPath(path, parent) {
+ var fullPath = (parent ? parent.fullPath : '') + path;
+ if (!routesByPath[fullPath]) {
+ routesByPath[fullPath] = new this.Route(path, parent);
+ this.driver.manageRoute(routesByPath[fullPath]);
+ }
+ return routesByPath[fullPath];
+}
+
+/**
+ * Retrieves the route registered via `name`.
+ *
+ * @param {String} name
+ * @return {MoreRouting.Route}
+ */
+MoreRouting.getRouteByName = function getRouteByName(name) {
+ var path = pathsByName[name];
+ if (!path) {
+ throw new Error('No route named "' + name + '" has been registered');
+ }
+ return this.getRouteByPath(path);
+}
+
+/**
+ * @param {String} path
+ * @return {MoreRouting.Route} The newly registered route.
+ */
+MoreRouting.registerNamedRoute = function registerNamedRoute(name, path, parent) {
+ if (pathsByName[name]) {
+ console.warn(
+ 'Overwriting route named "' + name + '" with path:', path,
+ 'previously:', pathsByName[name]);
+ }
+ var route = this.getRouteByPath(path, parent);
+ pathsByName[name] = route.fullPath;
+ return route;
+};
+
+// Route Shortcuts
+MoreRouting.urlFor = function urlFor(pathOrName, params) {
+ return this.getRoute(pathOrName).urlFor(params);
+};
+
+MoreRouting.navigateTo = function navigateTo(pathOrName, params) {
+ return this.getRoute(pathOrName).navigateTo(params);
+};
+
+MoreRouting.isCurrentUrl = function isCurrentUrl(pathOrName, params) {
+ return this.getRoute(pathOrName).isCurrentUrl(params);
+};
+
+// Utility
+
+/**
+ *
+ */
+MoreRouting.isPath = function isPath(pathOrName) {
+ return this.Route.isPath(pathOrName);
+}
+
+/**
+ * @param {...String} paths
+ */
+MoreRouting.joinPath = function joinPath(paths) {
+ return this.Route.joinPath.apply(this.Route, arguments);
+}
+
+// Driver Management
+
+var driver;
+Object.defineProperty(MoreRouting, 'driver', {
+ get: function getDriver() {
+ if (!driver) {
+ throw new Error('No routing driver configured. Did you forget <more-routing-config>?');
+ }
+ return driver;
+ },
+ set: function setDriver(newDriver) {
+ if (driver) {
+ console.warn('Changing routing drivers is not supported, ignoring. You should have only one <more-routing-config> on the page!');
+ return;
+ }
+ driver = newDriver;
+ }
+});
+
+})(window);
diff --git a/chrome/browser/resources/settings/routing/more_switch/more_switch.html b/chrome/browser/resources/settings/routing/more_switch/more_switch.html
new file mode 100644
index 0000000..b1b58a4
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_switch/more_switch.html
@@ -0,0 +1,20 @@
+<html><head>
+<link rel="import" href="chrome://resources/polymer/polymer/polymer.html">
+
+<!--
+`more-switch` provides `switch`-like behavior.
+
+The first template whose `when` statement evaluates truthy will be activated,
+the rest deactivated. `else` is equivalent to `when="{{true}}"`.
+
+ <more-switch>
+ <div when="{{foo == 1}}">One!</div>
+ <div when="{{foo == 2}}">Two!</div>
+ <div else>Default</div>
+ </more-switch>
+
+-->
+</head><body><polymer-element name="more-switch" assetpath="">
+
+</polymer-element>
+<script charset="utf-8" src="more-switch-extracted.js"></script></body></html>
diff --git a/chrome/browser/resources/settings/routing/more_switch/more_switch_extracted.js b/chrome/browser/resources/settings/routing/more_switch/more_switch_extracted.js
new file mode 100644
index 0000000..65b2959
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_switch/more_switch_extracted.js
@@ -0,0 +1,130 @@
+// Copyright 2015 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.
+
+ Polymer('more-switch', {
+ publish: {
+ /**
+ * The index of the selected element (0-indexed), or -1 if nothing is
+ * selected.
+ *
+ * @attribute selectedIndex
+ * @type number
+ * @default -1
+ */
+ selectedIndex: -1,
+ },
+
+ attached: function() {
+ // TODO(nevir): Handle childen that are added/removed after this point.
+ this.observeChildren();
+ this.evaluate();
+ },
+
+ selectedIndexChanged: function() {
+ // TODO(nevir): Why isn't type hinting working here?
+ this._setActiveChild(Number(this.selectedIndex), true);
+ },
+
+ /**
+ * Re-evaluates the conditions of each child, to determine which should be
+ * selected.
+ *
+ * Subclasses should call this whenever they think the truthiness of a
+ * child has changed.
+ *
+ * @method evaluate
+ * @protected
+ */
+ evaluate: function() {
+ var index = -1;
+ for (var i = 0, child; child = this.children[i]; i++) {
+ if (this.childIsTruthy(child, i)) {
+ index = i;
+ break;
+ }
+ }
+ this._setActiveChild(index, false);
+ },
+
+ // Subclass Hooks
+
+ /**
+ * Registers mutation observers for the conditions expressed by children.
+ *
+ * Subclasses should override this method if they need to express
+ * conditions in some other way.
+ *
+ * @method observeChildren
+ * @protected
+ */
+ observeChildren: function() {
+ // We observe attribute changes, as the assumption is that you will be
+ // using a `template-switch` within a template context. Thus, the `when`
+ // attributes will be already bound. We just have to infer their
+ // truthiness whenever they change.
+ this._observer = new MutationObserver(this._onAttributesChanged.bind(this));
+ for (var i = 0, child; child = this.children[i]; i++) {
+ this._observer.observe(child, {attributes: true});
+ }
+ },
+
+ /**
+ * @method childIsTruthy
+ * @protected
+ * @param {!HTMLElement} child The child element.
+ * @param {number} index The index of the child.
+ * @return {boolean} Whether the child's conditions are truthy.
+ */
+ childIsTruthy: function(child, index) {
+ return child.hasAttribute('else') || this._stringIsTruthy(child.getAttribute('when'));
+ },
+
+ /**
+ * @method activateChild
+ * @protected
+ * @param {!HTMLElement} child The child element.
+ * @param {number} index The index of the child.
+ * @param {boolean} external Whether this child is being activated by
+ * an external event (for example, `selectedIndex` was assigned to).
+ */
+ activateChild: function(child, index, external) {
+ for (var i = 0, child; child = this.children[i]; i++) {
+ if (i === index) {
+ child.removeAttribute('hidden');
+ } else {
+ child.setAttribute('hidden', '');
+ }
+ }
+ },
+
+ // Private Implementation
+
+ _onAttributesChanged: function(mutations) {
+ for (var i = 0, mutation; mutation = mutations[i]; i++) {
+ if (mutation.attributeName === 'when') {
+ this.evaluate();
+ return;
+ }
+ }
+ },
+
+ _setActiveChild: function(index, external) {
+ if (this._activeChild === index) return;
+ this._activeChild = index;
+ this.selectedIndex = index;
+
+ this.activateChild(this.children[index], index, external);
+ },
+
+ // TODO(nevir): This is dirty. Can we evaluate the binding expressions
+ // ourselves?
+ _stringIsTruthy: function(string) {
+ if (!string) return false;
+ if (string === 'false') return false;
+ if (string === '0') return false;
+ if (string === 'NaN') return false;
+ return true;
+ },
+ });
+
diff --git a/chrome/browser/resources/settings/routing/more_switch/template_switch.html b/chrome/browser/resources/settings/routing/more_switch/template_switch.html
new file mode 100644
index 0000000..5f62dac
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_switch/template_switch.html
@@ -0,0 +1,24 @@
+<html><head>
+<link rel="import" href="chrome://resources/polymer/polymer/polymer.html">
+
+<link rel="import" href="more-switch.html">
+
+<!--
+`template-switch` is like `more-switch` except it stamps templates on demand.
+
+This can be useful if you want to ensure that elements aren't hanging around,
+but be aware that templates aren't cheap.
+
+## Example:
+
+ <template-switch>
+ <template when="{{foo == 1}}">One!</template>
+ <template when="{{foo == 2}}">Two!</template>
+ <template else>Default</template>
+ </template-switch>
+
+-->
+</head><body><polymer-element name="template-switch" extends="more-switch" assetpath="">
+
+</polymer-element>
+<script charset="utf-8" src="template-switch-extracted.js"></script></body></html>
diff --git a/chrome/browser/resources/settings/routing/more_switch/template_switch_extracted.js b/chrome/browser/resources/settings/routing/more_switch/template_switch_extracted.js
new file mode 100644
index 0000000..4b57c32
--- /dev/null
+++ b/chrome/browser/resources/settings/routing/more_switch/template_switch_extracted.js
@@ -0,0 +1,35 @@
+// Copyright 2015 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.
+
+ Polymer('template-switch', {
+
+ /** @override */
+ activateChild: function(child, index, external) {
+ if (this._activeContent) {
+ this._activeContent.remove();
+ }
+ var template = this.children[index];
+ if (!template) return;
+
+ var model = this.modelForChild(template, index);
+ var fragment = template.createInstance(model, this.bindingDelegate);
+
+ this._activeContent = document.createElement('div');
+ this._activeContent.appendChild(fragment);
+ this.appendChild(this._activeContent);
+ },
+
+ /**
+ * @method modelForChild
+ * @protected
+ * @param {!HTMLElement} child The child element.
+ * @param {number} index The index of the child.
+ * @return {!Object} The object to use as a template model.
+ */
+ modelForChild: function(child, index) {
+ return this.templateInstance && this.templateInstance.model || {};
+ },
+
+ });
+
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd
index f00c016..ccee110 100644
--- a/chrome/browser/resources/settings/settings_resources.grd
+++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -115,6 +115,93 @@
<structure name="IDR_SETTINGS_PREF_TRACKER_JS"
file="pref_tracker/pref_tracker.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_DRIVER"
+ file="routing/more_routing/driver.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_DRIVER_EXTRACTED_JS"
+ file="routing/more_routing/driver_extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_DRIVER_HASH"
+ file="routing/more_routing/driver/hash.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_DRIVER_HASH_EXTRACTED_JS"
+ file="routing/more_routing/driver/hash_extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_DRIVER_MOCK"
+ file="routing/more_routing/driver/mock.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_DRIVER_MOCK_EXTRACTED_JS"
+ file="routing/more_routing/driver/mock_extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_DRIVER_PATH"
+ file="routing/more_routing/driver/path.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_DRIVER_PATH_EXTRACTED_JS"
+ file="routing/more_routing/driver/path_extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_MORE_ROUTE_HTML"
+ file="routing/more_routing/more_route.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_MORE_ROUTE_EXTRACTED_JS"
+ file="routing/more_routing/more_route_extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_MORE_ROUTE_CONTEXT_AWARE_HTML"
+ file="routing/more_routing/more_route_context_aware.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_MORE_ROUTE_CONTEXT_AWARE_EXTRACTED_JS"
+ file="routing/more_routing/more_route_context_aware_extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_MORE_ROUTE_ITEM_HTML"
+ file="routing/more_routing/more_route_item.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_MORE_ROUTE_ITEM_EXTRACTED_JS"
+ file="routing/more_routing/more_route_item_extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_MORE_ROUTE_SELECTION_HTML"
+ file="routing/more_routing/more_route_selection.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_MORE_ROUTE_SELECTION_EXTRACTED_JS"
+ file="routing/more_routing/more_route_selection_extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_MORE_ROUTE_SELECTOR_HTML"
+ file="routing/more_routing/more_route_selector.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_MORE_ROUTE_SELECTOR_EXTRACTED_JS"
+ file="routing/more_routing/more_route_selector_extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_MORE_ROUTE_SWITCH_HTML"
+ file="routing/more_routing/more_route_switch.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_MORE_ROUTE_SWITCH_EXTRACTED_JS"
+ file="routing/more_routing/more_route_switch_extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_MORE_ROUTING_CONFIG_HTML"
+ file="routing/more_routing/more_routing_config.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_MORE_ROUTING_CONFIG_EXTRACTED_JS"
+ file="routing/more_routing/more_routing_config_extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_MORE_ROUTING_HTML"
+ file="routing/more_routing/more_routing.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_POLYMER_EXPRESSIONS_HTML"
+ file="routing/more_routing/polymer_expressions.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_POLYMER_EXPRESSIONS_EXTRACTED_JS"
+ file="routing/more_routing/polymer_expressions_extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_ROUTE_HTML"
+ file="routing/more_routing/route.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_ROUTE_EXTRACTED_JS"
+ file="routing/more_routing/route_extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_ROUTING_HTML"
+ file="routing/more_routing/routing.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_ROUTING_EXTRACTED_JS"
+ file="routing/more_routing/routing_extracted.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_SETTINGS_HTML"
file="settings.html"
type="chrome_html" />
diff --git a/tools/licenses.py b/tools/licenses.py
index 597dcea..95378c8 100755
--- a/tools/licenses.py
+++ b/tools/licenses.py
@@ -84,6 +84,8 @@ PRUNE_DIRS = (VCS_METADATA_DIRS +
ADDITIONAL_PATHS = (
os.path.join('breakpad'),
os.path.join('chrome', 'common', 'extensions', 'docs', 'examples'),
+ os.path.join('chrome', 'browser', 'resources', 'settings', 'routing',
+ 'more_routing'),
os.path.join('chrome', 'test', 'chromeos', 'autotest'),
os.path.join('chrome', 'test', 'data'),
os.path.join('native_client'),