1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/addon-sdk/source/lib/sdk/util/match-pattern.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,120 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +"use strict"; 1.9 + 1.10 +module.metadata = { 1.11 + "stability": "unstable" 1.12 +}; 1.13 + 1.14 +const { URL } = require('../url'); 1.15 +const cache = {}; 1.16 + 1.17 +function MatchPattern(pattern) { 1.18 + if (cache[pattern]) return cache[pattern]; 1.19 + 1.20 + if (typeof pattern.test == "function") { 1.21 + 1.22 + // For compatibility with -moz-document rules, we require the RegExp's 1.23 + // global, ignoreCase, and multiline flags to be set to false. 1.24 + if (pattern.global) { 1.25 + throw new Error("A RegExp match pattern cannot be set to `global` " + 1.26 + "(i.e. //g)."); 1.27 + } 1.28 + if (pattern.ignoreCase) { 1.29 + throw new Error("A RegExp match pattern cannot be set to `ignoreCase` " + 1.30 + "(i.e. //i)."); 1.31 + } 1.32 + if (pattern.multiline) { 1.33 + throw new Error("A RegExp match pattern cannot be set to `multiline` " + 1.34 + "(i.e. //m)."); 1.35 + } 1.36 + 1.37 + this.regexp = pattern; 1.38 + } 1.39 + else { 1.40 + let firstWildcardPosition = pattern.indexOf("*"); 1.41 + let lastWildcardPosition = pattern.lastIndexOf("*"); 1.42 + if (firstWildcardPosition != lastWildcardPosition) 1.43 + throw new Error("There can be at most one '*' character in a wildcard."); 1.44 + 1.45 + if (firstWildcardPosition == 0) { 1.46 + if (pattern.length == 1) 1.47 + this.anyWebPage = true; 1.48 + else if (pattern[1] != ".") 1.49 + throw new Error("Expected a *.<domain name> string, got: " + pattern); 1.50 + else 1.51 + this.domain = pattern.substr(2); 1.52 + } 1.53 + else { 1.54 + if (pattern.indexOf(":") == -1) { 1.55 + throw new Error("When not using *.example.org wildcard, the string " + 1.56 + "supplied is expected to be either an exact URL to " + 1.57 + "match or a URL prefix. The provided string ('" + 1.58 + pattern + "') is unlikely to match any pages."); 1.59 + } 1.60 + 1.61 + if (firstWildcardPosition == -1) 1.62 + this.exactURL = pattern; 1.63 + else if (firstWildcardPosition == pattern.length - 1) 1.64 + this.urlPrefix = pattern.substr(0, pattern.length - 1); 1.65 + else { 1.66 + throw new Error("The provided wildcard ('" + pattern + "') has a '*' " + 1.67 + "in an unexpected position. It is expected to be the " + 1.68 + "first or the last character in the wildcard."); 1.69 + } 1.70 + } 1.71 + } 1.72 + 1.73 + cache[pattern] = this; 1.74 +} 1.75 + 1.76 +MatchPattern.prototype = { 1.77 + 1.78 + test: function MatchPattern_test(urlStr) { 1.79 + try { 1.80 + var url = URL(urlStr); 1.81 + } 1.82 + catch (err) { 1.83 + return false; 1.84 + } 1.85 + 1.86 + // Test the URL against a RegExp pattern. For compatibility with 1.87 + // -moz-document rules, we require the RegExp to match the entire URL, 1.88 + // so we not only test for a match, we also make sure the matched string 1.89 + // is the entire URL string. 1.90 + // 1.91 + // Assuming most URLs don't match most match patterns, we call `test` for 1.92 + // speed when determining whether or not the URL matches, then call `exec` 1.93 + // for the small subset that match to make sure the entire URL matches. 1.94 + // 1.95 + if (this.regexp && this.regexp.test(urlStr) && 1.96 + this.regexp.exec(urlStr)[0] == urlStr) 1.97 + return true; 1.98 + 1.99 + if (this.anyWebPage && /^(https?|ftp)$/.test(url.scheme)) 1.100 + return true; 1.101 + if (this.exactURL && this.exactURL == urlStr) 1.102 + return true; 1.103 + 1.104 + // Tests the urlStr against domain and check if 1.105 + // wildcard submitted (*.domain.com), it only allows 1.106 + // subdomains (sub.domain.com) or from the root (http://domain.com) 1.107 + // and reject non-matching domains (otherdomain.com) 1.108 + // bug 856913 1.109 + if (this.domain && url.host && 1.110 + (url.host === this.domain || 1.111 + url.host.slice(-this.domain.length - 1) === "." + this.domain)) 1.112 + return true; 1.113 + if (this.urlPrefix && 0 == urlStr.indexOf(this.urlPrefix)) 1.114 + return true; 1.115 + 1.116 + return false; 1.117 + }, 1.118 + 1.119 + toString: function () '[object MatchPattern]' 1.120 + 1.121 +}; 1.122 + 1.123 +exports.MatchPattern = MatchPattern;