From a353298ada31dbbacee612d6c9f79b8495708499 Mon Sep 17 00:00:00 2001 From: Raine Makelainen Date: Mon, 18 Apr 2016 20:34:05 +0300 Subject: [PATCH] [embedlite-components] Add support for site specific UA override. Contributes to JB#34904 This makes possible to use general.useragent.override.* overrides with simple replace syntax given that complex override is not applied. Instantiation of the UserAgent is deferred a bit so that we do not end up initializing UserAgentOverrides before general.useragent.override is applied. As UserAgent was initialized on that application startup, the simple hash separated user agent fixing did not work. This happened because nsIHttpProtocolHandler was not yet aware of the override. Thus, causing UserAgentOverrides to fail to replace ua. --- jscomps/EmbedLiteJSComponents.manifest | 1 + jscomps/UserAgentOverrideHelper.js | 93 +++++++++++++++++++------- 2 files changed, 71 insertions(+), 23 deletions(-) diff --git a/jscomps/EmbedLiteJSComponents.manifest b/jscomps/EmbedLiteJSComponents.manifest index 00b41b3..e3ec218 100644 --- a/jscomps/EmbedLiteJSComponents.manifest +++ b/jscomps/EmbedLiteJSComponents.manifest @@ -64,6 +64,7 @@ category app-startup EmbedLiteErrorPageHandler service,@mozilla.org/embedlite-er # UserAgentOverrideHelper.js component {69d68654-b5a0-11e2-bb91-2b8ad5eb98ac} UserAgentOverrideHelper.js contract @mozilla.org/embedlite-uahelper-component;1 {69d68654-b5a0-11e2-bb91-2b8ad5eb98ac} +contract @mozilla.org/dom/site-specific-user-agent;1 {69d68654-b5a0-11e2-bb91-2b8ad5eb98ac} category app-startup UserAgentOverrideHelper service,@mozilla.org/embedlite-uahelper-component;1 # XPIDialogService.js diff --git a/jscomps/UserAgentOverrideHelper.js b/jscomps/UserAgentOverrideHelper.js index 664e140..40e93d7 100644 --- a/jscomps/UserAgentOverrideHelper.js +++ b/jscomps/UserAgentOverrideHelper.js @@ -25,10 +25,22 @@ UserAgentOverrideHelper.prototype = { // Engine DownloadManager notifications case "app-startup": { dump("UserAgentOverrideHelper app-startup\n"); - UserAgent.init(); + Services.obs.addObserver(this, "embedliteviewcreated", true); Services.obs.addObserver(this, "xpcom-shutdown", false); + Services.prefs.addObserver("general.useragent.override", this, false); + break; + } + case "nsPref:changed": { + if (aData == "general.useragent.override") { + UserAgent.init(); + } break; } + case "embedliteviewcreated": { + UserAgent.init(); + break; + } + case "xpcom-shutdown": { dump("UserAgentOverrideHelper xpcom-shutdown\n"); Services.obs.removeObserver(this, "xpcom-shutdown", false); @@ -38,29 +50,30 @@ UserAgentOverrideHelper.prototype = { } }, - QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference, Ci.nsIFormSubmitObserver]) + getUserAgentForURIAndWindow: function ssua_getUserAgentForURIAndWindow(aURI, aWindow) { + return UserAgent.getUserAgentForWindow(aURI, aWindow) + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsISiteSpecificUserAgent, Ci.nsIObserver, + Ci.nsISupportsWeakReference, Ci.nsIFormSubmitObserver]) }; var UserAgent = { _desktopMode: false, + _customUA: null, + overrideMap: new Map, + initilized: false, DESKTOP_UA: null, GOOGLE_DOMAIN: /(^|\.)google\.com$/, GOOGLE_MAPS_DOMAIN: /(^|\.)maps\.google\.com$/, YOUTUBE_DOMAIN: /(^|\.)youtube\.com$/, NOKIA_HERE_DOMAIN: /(^|\.)here\.com$/, - _customUA: null, - getCustomUserAgent: function() { - if (Services.prefs.prefHasUserValue("general.useragent.override")) { - let ua = Services.prefs.getCharPref("general.useragent.override"); - return ua; - } - else { - return null; + init: function ua_init() { + if (this.initilized) { + return } - }, - init: function ua_init() { Services.obs.addObserver(this, "DesktopMode:Change", false); Services.prefs.addObserver("general.useragent.override", this, false); this._customUA = this.getCustomUserAgent(); @@ -71,15 +84,28 @@ var UserAgent = { .getService(Ci.nsIHttpProtocolHandler).userAgent .replace(/Android; [a-zA-Z]+/, "X11; Linux x86_64") .replace(/Gecko\/[0-9\.]+/, "Gecko/20100101"); + this.initilized = true; + }, + + getCustomUserAgent: function() { + if (Services.prefs.prefHasUserValue("general.useragent.override")) { + let ua = Services.prefs.getCharPref("general.useragent.override"); + return ua; + } else { + return null; + } }, - getUserAgentForUriAndTab: function ua_getUserAgentForUriAndTab(aUri, defaultUA) { + getDefaultUserAgent : function ua_getDefaultUserAgent() { // Send desktop UA if "Request Desktop Site" is enabled. if (this._desktopMode) return this.DESKTOP_UA; - let ua = this._customUA ? this._customUA : defaultUA; + return this._customUA ? this._customUA : defaultUA; + }, + getUserAgentForUriAndTab: function ua_getUserAgentForUriAndTab(aUri) { + let ua = this.getDefaultUserAgent(); // Not all schemes have a host member. if (aUri.schemeIs("http") || aUri.schemeIs("https")) { if (this.GOOGLE_DOMAIN.test(aUri.host)) { @@ -112,7 +138,7 @@ var UserAgent = { } } - return ua; + return ""; }, uninit: function ua_uninit() { @@ -121,18 +147,39 @@ var UserAgent = { UserAgentOverrides.uninit(); }, + // Complex override calls this first. onRequest: function(channel, defaultUA) { let channelWindow = this._getWindowForRequest(channel); - let ua = this.getUserAgentForUriAndTab(channel.URI, defaultUA); - if (ua) - channel.setRequestHeader("User-Agent", ua, false); + let ua = ""; + let host = channel.URI.asciiHost + let windowHost = channelWindow && channelWindow.location.hostname || ""; + + if (!channelWindow) { + ua = this.getDefaultUserAgent() + } else if (this.overrideMap.has(host)) { + ua = this.overrideMap.get(host); + } else if (this.overrideMap.has(windowHost)) { + ua = this.overrideMap.get(windowHost); + } else { + ua = this.getUserAgentForWindow(channel.URI, channelWindow); + } + return ua }, - getUserAgentForWindow: function ua_getUserAgentForWindow(aWindow, defaultUA) { - let tab = BrowserApp.getTabForWindow(aWindow.top); - if (tab) - return this.getUserAgentForUriAndTab(tab.browser.currentURI, tab, defaultUA); - return defaultUA; + // Called if onRequest returns empty user-agent. + getUserAgentForWindow: function ua_getUserAgentForWindow(aUri, aWindow) { + // Try to pick 'general.useragent.override.*' + let ua = UserAgentOverrides.getOverrideForURI(aUri) + if (!ua) { + ua = this.getUserAgentForUriAndTab(aUri); + } + + if (ua) { + this.overrideMap.set(aUri.asciiHost, ua) + return ua + } + + return this.getDefaultUserAgent(); }, _getRequestLoadContext: function ua_getRequestLoadContext(aRequest) {