| Index: third_party/WebKit/Source/devtools/front_end/product_registry_impl/ProductRegistryImpl.js
|
| diff --git a/third_party/WebKit/Source/devtools/front_end/product_registry_impl/ProductRegistryImpl.js b/third_party/WebKit/Source/devtools/front_end/product_registry_impl/ProductRegistryImpl.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..977720e5940c056a8954e3260af210c7a2dfcba5
|
| --- /dev/null
|
| +++ b/third_party/WebKit/Source/devtools/front_end/product_registry_impl/ProductRegistryImpl.js
|
| @@ -0,0 +1,143 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +/**
|
| + * @implements {ProductRegistry.Registry}
|
| + */
|
| +ProductRegistryImpl.Registry = class {
|
| + constructor() {
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!Common.ParsedURL} parsedUrl
|
| + * @return {?string}
|
| + */
|
| + nameForUrl(parsedUrl) {
|
| + var entry = this.entryForUrl(parsedUrl);
|
| + if (entry)
|
| + return entry.name;
|
| + return null;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!Common.ParsedURL} parsedUrl
|
| + * @return {?ProductRegistry.Registry.ProductEntry}
|
| + */
|
| + entryForUrl(parsedUrl) {
|
| + if (parsedUrl.isDataURL())
|
| + return null;
|
| + // TODO(allada) This should be expanded to allow paths as as well as domain to find a product.
|
| + var productsByDomainHash = ProductRegistryImpl._productsByDomainHash;
|
| + // Remove leading www. if it is the only subdomain.
|
| + var domain = parsedUrl.domain().replace(/^www\.(?=[^.]+\.[^.]+$)/, '');
|
| +
|
| + var previousIndex = -1;
|
| + var index = -1;
|
| + // Ensure we loop with full domain first, but do not loop over last part (ie: ".com").
|
| + for (var nextIndex = domain.indexOf('.'); nextIndex !== -1; nextIndex = domain.indexOf('.', nextIndex + 1)) {
|
| + var previousSubdomain = domain.substring(previousIndex + 1, index);
|
| + var subDomain = domain.substring(index + 1);
|
| + var prefixes = productsByDomainHash.get(ProductRegistryImpl._hashForDomain(subDomain));
|
| + previousIndex = index;
|
| + index = nextIndex;
|
| + if (!prefixes)
|
| + continue;
|
| + // Exact match domains are always highest priority.
|
| + if ('' in prefixes && domain === subDomain)
|
| + return prefixes[''];
|
| + if (previousSubdomain) {
|
| + for (var prefix in prefixes) {
|
| + var domainPrefix = previousSubdomain.substr(0, prefix.length);
|
| + if (domainPrefix === prefix && prefix !== '')
|
| + return prefixes[prefix];
|
| + }
|
| + }
|
| + // Process wildcard subdomain if no better match found.
|
| + if (prefixes && '*' in prefixes)
|
| + return prefixes['*'];
|
| + }
|
| + return null;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!Common.ParsedURL} parsedUrl
|
| + * @return {?number}
|
| + */
|
| + typeForUrl(parsedUrl) {
|
| + var entry = this.entryForUrl(parsedUrl);
|
| + if (entry)
|
| + return entry.type;
|
| + return null;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {!SDK.ResourceTreeFrame} frame
|
| + * @return {?ProductRegistry.Registry.ProductEntry}
|
| + */
|
| + entryForFrame(frame) {
|
| + var entry;
|
| + if (frame.url)
|
| + entry = this.entryForUrl(new Common.ParsedURL(frame.url));
|
| + if (entry)
|
| + return entry;
|
| + // We are not caching the frame url result because it may change.
|
| + var symbol = ProductRegistryImpl.Registry._productEntryForFrameSymbol;
|
| + if (!(symbol in frame))
|
| + frame[symbol] = this._lookupStackTraceEntryForFrame(frame);
|
| + return frame[symbol];
|
| + }
|
| +
|
| + /**
|
| + * @param {!SDK.ResourceTreeFrame} frame
|
| + * @return {?ProductRegistry.Registry.ProductEntry}
|
| + */
|
| + _lookupStackTraceEntryForFrame(frame) {
|
| + var stackTrace = frame.creationStackTrace();
|
| + var entry;
|
| + while (stackTrace) {
|
| + for (var stack of stackTrace.callFrames) {
|
| + if (stack.url)
|
| + entry = this.entryForUrl(new Common.ParsedURL(stack.url));
|
| + if (entry)
|
| + return entry;
|
| + }
|
| + stackTrace = frame.parent;
|
| + }
|
| + return null;
|
| + }
|
| +};
|
| +
|
| +ProductRegistryImpl.Registry._productEntryForFrameSymbol = Symbol('ProductEntryForFrame');
|
| +
|
| +/**
|
| + * @param {string} domain
|
| + * @return {string}
|
| + */
|
| +ProductRegistryImpl._hashForDomain = function(domain) {
|
| + return ProductRegistryImpl.sha1(domain).substr(0, 16);
|
| +};
|
| +
|
| +/**
|
| + * @param {!Array<string>} productNames
|
| + * @param {!Array<!{hash: string, prefixes: !Object<string, !{product: number, type: (number|undefined)}>}>} data
|
| + */
|
| +ProductRegistryImpl.register = function(productNames, data) {
|
| + for (var i = 0; i < data.length; i++) {
|
| + var entry = data[i];
|
| + var prefixes = {};
|
| + for (var prefix in entry.prefixes) {
|
| + var prefixEntry = entry.prefixes[prefix];
|
| + var type = prefixEntry.type !== undefined ? prefixEntry.type : null;
|
| + prefixes[prefix] = {name: productNames[prefixEntry.product], type: type};
|
| + }
|
| + ProductRegistryImpl._productsByDomainHash.set(entry.hash, prefixes);
|
| + }
|
| +};
|
| +
|
| +/** @type {!Map<string, !Object<string, !ProductRegistry.Registry.ProductEntry>>}} */
|
| +ProductRegistryImpl._productsByDomainHash = new Map();
|
|
|