netwerk/protocol/http/UserAgentOverrides.jsm

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 "use strict";
     7 this.EXPORTED_SYMBOLS = [ "UserAgentOverrides" ];
     9 const Ci = Components.interfaces;
    10 const Cc = Components.classes;
    12 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
    13 Components.utils.import("resource://gre/modules/Services.jsm");
    14 Components.utils.import("resource://gre/modules/UserAgentUpdates.jsm");
    16 const OVERRIDE_MESSAGE = "Useragent:GetOverride";
    17 const PREF_OVERRIDES_ENABLED = "general.useragent.site_specific_overrides";
    18 const DEFAULT_UA = Cc["@mozilla.org/network/protocol;1?name=http"]
    19                      .getService(Ci.nsIHttpProtocolHandler)
    20                      .userAgent;
    21 const MAX_OVERRIDE_FOR_HOST_CACHE_SIZE = 250;
    23 XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
    24                                   "@mozilla.org/parentprocessmessagemanager;1",
    25                                   "nsIMessageListenerManager");  // Might have to make this broadcast?
    27 var gPrefBranch;
    28 var gOverrides = new Map;
    29 var gUpdatedOverrides;
    30 var gOverrideForHostCache = new Map;
    31 var gInitialized = false;
    32 var gOverrideFunctions = [
    33   function (aHttpChannel) UserAgentOverrides.getOverrideForURI(aHttpChannel.URI)
    34 ];
    35 var gBuiltUAs = new Map;
    37 this.UserAgentOverrides = {
    38   init: function uao_init() {
    39     if (gInitialized)
    40       return;
    42     gPrefBranch = Services.prefs.getBranch("general.useragent.override.");
    43     gPrefBranch.addObserver("", buildOverrides, false);
    45     ppmm.addMessageListener(OVERRIDE_MESSAGE, this);
    46     Services.prefs.addObserver(PREF_OVERRIDES_ENABLED, buildOverrides, false);
    48     try {
    49       Services.obs.addObserver(HTTP_on_modify_request, "http-on-modify-request", false);
    50     } catch (x) {
    51       // The http-on-modify-request notification is disallowed in content processes.
    52     }
    54     UserAgentUpdates.init(function(overrides) {
    55       gOverrideForHostCache.clear();
    56       if (overrides) {
    57         for (let domain in overrides) {
    58           overrides[domain] = getUserAgentFromOverride(overrides[domain]);
    59         }
    60         overrides.get = function(key) this[key];
    61       }
    62       gUpdatedOverrides = overrides;
    63     });
    65     buildOverrides();
    66     gInitialized = true;
    67   },
    69   addComplexOverride: function uao_addComplexOverride(callback) {
    70     // Add to front of array so complex overrides have precedence
    71     gOverrideFunctions.unshift(callback);
    72   },
    74   getOverrideForURI: function uao_getOverrideForURI(aURI) {
    75     let host = aURI.asciiHost;
    76     if (!gInitialized ||
    77         (!gOverrides.size && !gUpdatedOverrides) ||
    78         !(host)) {
    79       return null;
    80     }
    82     let override = gOverrideForHostCache.get(host);
    83     if (override !== undefined)
    84       return override;
    86     function findOverride(overrides) {
    87       let searchHost = host;
    88       let userAgent = overrides.get(searchHost);
    90       while (!userAgent) {
    91         let dot = searchHost.indexOf('.');
    92         if (dot === -1) {
    93           return null;
    94         }
    95         searchHost = searchHost.slice(dot + 1);
    96         userAgent = overrides.get(searchHost);
    97       }
    98       return userAgent;
    99     }
   101     override = (gOverrides.size && findOverride(gOverrides))
   102             || (gUpdatedOverrides && findOverride(gUpdatedOverrides));
   104     if (gOverrideForHostCache.size >= MAX_OVERRIDE_FOR_HOST_CACHE_SIZE) {
   105       gOverrideForHostCache.clear();
   106     }
   107     gOverrideForHostCache.set(host, override);
   109     return override;
   110   },
   112   uninit: function uao_uninit() {
   113     if (!gInitialized)
   114       return;
   115     gInitialized = false;
   117     gPrefBranch.removeObserver("", buildOverrides);
   119     Services.prefs.removeObserver(PREF_OVERRIDES_ENABLED, buildOverrides);
   121     Services.obs.removeObserver(HTTP_on_modify_request, "http-on-modify-request");
   122   },
   124   receiveMessage: function(aMessage) {
   125     let name = aMessage.name;
   126     switch (name) {
   127       case OVERRIDE_MESSAGE:
   128         let uri = aMessage.data.uri;
   129         return this.getOverrideForURI(uri);
   130       default:
   131         throw("Wrong Message in UserAgentOverride: " + name);
   132     }
   133   }
   134 };
   136 function getUserAgentFromOverride(override)
   137 {
   138   let userAgent = gBuiltUAs.get(override);
   139   if (userAgent !== undefined) {
   140     return userAgent;
   141   }
   142   let [search, replace] = override.split("#", 2);
   143   if (search && replace) {
   144     userAgent = DEFAULT_UA.replace(new RegExp(search, "g"), replace);
   145   } else {
   146     userAgent = override;
   147   }
   148   gBuiltUAs.set(override, userAgent);
   149   return userAgent;
   150 }
   152 function buildOverrides() {
   153   gOverrides.clear();
   154   gOverrideForHostCache.clear();
   156   if (!Services.prefs.getBoolPref(PREF_OVERRIDES_ENABLED))
   157     return;
   159   let builtUAs = new Map;
   160   let domains = gPrefBranch.getChildList("");
   162   for (let domain of domains) {
   163     let override = gPrefBranch.getCharPref(domain);
   164     let userAgent = getUserAgentFromOverride(override);
   166     if (userAgent != DEFAULT_UA) {
   167       gOverrides.set(domain, userAgent);
   168     }
   169   }
   170 }
   172 function HTTP_on_modify_request(aSubject, aTopic, aData) {
   173   let channel = aSubject.QueryInterface(Ci.nsIHttpChannel);
   175   for (let callback of gOverrideFunctions) {
   176     let modifiedUA = callback(channel, DEFAULT_UA);
   177     if (modifiedUA) {
   178       channel.setRequestHeader("User-Agent", modifiedUA, false);
   179       return;
   180     }
   181   }
   182 }

mercurial