Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | // -*- Mode: javascript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
michael@0 | 2 | // This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | // License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. |
michael@0 | 5 | |
michael@0 | 6 | this.EXPORTED_SYMBOLS = ["RemoteWebProgressManager"]; |
michael@0 | 7 | |
michael@0 | 8 | const Ci = Components.interfaces; |
michael@0 | 9 | const Cc = Components.classes; |
michael@0 | 10 | const Cu = Components.utils; |
michael@0 | 11 | |
michael@0 | 12 | Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
michael@0 | 13 | |
michael@0 | 14 | function newURI(spec) |
michael@0 | 15 | { |
michael@0 | 16 | return Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService) |
michael@0 | 17 | .newURI(spec, null, null); |
michael@0 | 18 | } |
michael@0 | 19 | |
michael@0 | 20 | function RemoteWebProgressRequest(spec) |
michael@0 | 21 | { |
michael@0 | 22 | this.uri = newURI(spec); |
michael@0 | 23 | } |
michael@0 | 24 | |
michael@0 | 25 | RemoteWebProgressRequest.prototype = { |
michael@0 | 26 | QueryInterface : XPCOMUtils.generateQI([Ci.nsIChannel]), |
michael@0 | 27 | |
michael@0 | 28 | get URI() { return this.uri.clone(); } |
michael@0 | 29 | }; |
michael@0 | 30 | |
michael@0 | 31 | function RemoteWebProgress(aManager, aIsTopLevel) { |
michael@0 | 32 | this._manager = aManager; |
michael@0 | 33 | |
michael@0 | 34 | this._isLoadingDocument = false; |
michael@0 | 35 | this._DOMWindow = null; |
michael@0 | 36 | this._isTopLevel = aIsTopLevel; |
michael@0 | 37 | this._loadType = 0; |
michael@0 | 38 | } |
michael@0 | 39 | |
michael@0 | 40 | RemoteWebProgress.prototype = { |
michael@0 | 41 | NOTIFY_STATE_REQUEST: 0x00000001, |
michael@0 | 42 | NOTIFY_STATE_DOCUMENT: 0x00000002, |
michael@0 | 43 | NOTIFY_STATE_NETWORK: 0x00000004, |
michael@0 | 44 | NOTIFY_STATE_WINDOW: 0x00000008, |
michael@0 | 45 | NOTIFY_STATE_ALL: 0x0000000f, |
michael@0 | 46 | NOTIFY_PROGRESS: 0x00000010, |
michael@0 | 47 | NOTIFY_STATUS: 0x00000020, |
michael@0 | 48 | NOTIFY_SECURITY: 0x00000040, |
michael@0 | 49 | NOTIFY_LOCATION: 0x00000080, |
michael@0 | 50 | NOTIFY_REFRESH: 0x00000100, |
michael@0 | 51 | NOTIFY_ALL: 0x000001ff, |
michael@0 | 52 | |
michael@0 | 53 | get isLoadingDocument() { return this._isLoadingDocument }, |
michael@0 | 54 | get DOMWindow() { return this._DOMWindow; }, |
michael@0 | 55 | get DOMWindowID() { return 0; }, |
michael@0 | 56 | get isTopLevel() { return this._isTopLevel }, |
michael@0 | 57 | get loadType() { return this._loadType; }, |
michael@0 | 58 | |
michael@0 | 59 | addProgressListener: function (aListener) { |
michael@0 | 60 | this._manager.addProgressListener(aListener); |
michael@0 | 61 | }, |
michael@0 | 62 | |
michael@0 | 63 | removeProgressListener: function (aListener) { |
michael@0 | 64 | this._manager.removeProgressListener(aListener); |
michael@0 | 65 | } |
michael@0 | 66 | }; |
michael@0 | 67 | |
michael@0 | 68 | function RemoteWebProgressManager (aBrowser) { |
michael@0 | 69 | this._browser = aBrowser; |
michael@0 | 70 | this._topLevelWebProgress = new RemoteWebProgress(this, true); |
michael@0 | 71 | this._progressListeners = []; |
michael@0 | 72 | |
michael@0 | 73 | this._browser.messageManager.addMessageListener("Content:StateChange", this); |
michael@0 | 74 | this._browser.messageManager.addMessageListener("Content:LocationChange", this); |
michael@0 | 75 | this._browser.messageManager.addMessageListener("Content:SecurityChange", this); |
michael@0 | 76 | this._browser.messageManager.addMessageListener("Content:StatusChange", this); |
michael@0 | 77 | } |
michael@0 | 78 | |
michael@0 | 79 | RemoteWebProgressManager.prototype = { |
michael@0 | 80 | get topLevelWebProgress() { |
michael@0 | 81 | return this._topLevelWebProgress; |
michael@0 | 82 | }, |
michael@0 | 83 | |
michael@0 | 84 | addProgressListener: function (aListener) { |
michael@0 | 85 | let listener = aListener.QueryInterface(Ci.nsIWebProgressListener); |
michael@0 | 86 | this._progressListeners.push(listener); |
michael@0 | 87 | }, |
michael@0 | 88 | |
michael@0 | 89 | removeProgressListener: function (aListener) { |
michael@0 | 90 | this._progressListeners = |
michael@0 | 91 | this._progressListeners.filter(l => l != aListener); |
michael@0 | 92 | }, |
michael@0 | 93 | |
michael@0 | 94 | _fixSSLStatusAndState: function (aStatus, aState) { |
michael@0 | 95 | let deserialized = null; |
michael@0 | 96 | if (aStatus) { |
michael@0 | 97 | let helper = Cc["@mozilla.org/network/serialization-helper;1"] |
michael@0 | 98 | .getService(Components.interfaces.nsISerializationHelper); |
michael@0 | 99 | |
michael@0 | 100 | deserialized = helper.deserializeObject(aStatus) |
michael@0 | 101 | deserialized.QueryInterface(Ci.nsISSLStatus); |
michael@0 | 102 | } |
michael@0 | 103 | |
michael@0 | 104 | // We must check the Extended Validation (EV) state here, on the chrome |
michael@0 | 105 | // process, because NSS is needed for that determination. |
michael@0 | 106 | if (deserialized && deserialized.isExtendedValidation) |
michael@0 | 107 | aState |= Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL; |
michael@0 | 108 | |
michael@0 | 109 | return [deserialized, aState]; |
michael@0 | 110 | }, |
michael@0 | 111 | |
michael@0 | 112 | setCurrentURI: function (aURI) { |
michael@0 | 113 | // This function is simpler than nsDocShell::SetCurrentURI since |
michael@0 | 114 | // it doesn't have to deal with child docshells. |
michael@0 | 115 | let webNavigation = this._browser.webNavigation; |
michael@0 | 116 | webNavigation._currentURI = aURI; |
michael@0 | 117 | |
michael@0 | 118 | let webProgress = this.topLevelWebProgress; |
michael@0 | 119 | for (let p of this._progressListeners) { |
michael@0 | 120 | p.onLocationChange(webProgress, null, aURI); |
michael@0 | 121 | } |
michael@0 | 122 | }, |
michael@0 | 123 | |
michael@0 | 124 | _callProgressListeners: function(methodName, ...args) { |
michael@0 | 125 | for (let p of this._progressListeners) { |
michael@0 | 126 | if (p[methodName]) { |
michael@0 | 127 | try { |
michael@0 | 128 | p[methodName].apply(p, args); |
michael@0 | 129 | } catch (ex) { |
michael@0 | 130 | Cu.reportError("RemoteWebProgress failed to call " + methodName + ": " + ex + "\n"); |
michael@0 | 131 | } |
michael@0 | 132 | } |
michael@0 | 133 | } |
michael@0 | 134 | }, |
michael@0 | 135 | |
michael@0 | 136 | receiveMessage: function (aMessage) { |
michael@0 | 137 | let json = aMessage.json; |
michael@0 | 138 | let objects = aMessage.objects; |
michael@0 | 139 | |
michael@0 | 140 | // The top-level WebProgress is always the same, but because we don't |
michael@0 | 141 | // really have a concept of subframes/content we always creat a new object |
michael@0 | 142 | // for those. |
michael@0 | 143 | let webProgress = json.isTopLevel ? this._topLevelWebProgress |
michael@0 | 144 | : new RemoteWebProgress(this, false); |
michael@0 | 145 | |
michael@0 | 146 | // The WebProgressRequest object however is always dynamic. |
michael@0 | 147 | let request = json.requestURI ? new RemoteWebProgressRequest(json.requestURI) |
michael@0 | 148 | : null; |
michael@0 | 149 | |
michael@0 | 150 | // Update the actual WebProgress fields. |
michael@0 | 151 | webProgress._isLoadingDocument = json.isLoadingDocument; |
michael@0 | 152 | webProgress._DOMWindow = objects.DOMWindow; |
michael@0 | 153 | webProgress._loadType = json.loadType; |
michael@0 | 154 | |
michael@0 | 155 | if (json.isTopLevel) { |
michael@0 | 156 | this._browser._contentWindow = objects.contentWindow; |
michael@0 | 157 | this._browser._documentContentType = json.documentContentType; |
michael@0 | 158 | } |
michael@0 | 159 | |
michael@0 | 160 | switch (aMessage.name) { |
michael@0 | 161 | case "Content:StateChange": |
michael@0 | 162 | this._callProgressListeners("onStateChange", webProgress, request, json.stateFlags, json.status); |
michael@0 | 163 | break; |
michael@0 | 164 | |
michael@0 | 165 | case "Content:LocationChange": |
michael@0 | 166 | let location = newURI(json.location); |
michael@0 | 167 | let flags = json.flags; |
michael@0 | 168 | |
michael@0 | 169 | if (json.isTopLevel) { |
michael@0 | 170 | this._browser.webNavigation._currentURI = location; |
michael@0 | 171 | this._browser.webNavigation.canGoBack = json.canGoBack; |
michael@0 | 172 | this._browser.webNavigation.canGoForward = json.canGoForward; |
michael@0 | 173 | this._browser._characterSet = json.charset; |
michael@0 | 174 | this._browser._documentURI = newURI(json.documentURI); |
michael@0 | 175 | this._browser._imageDocument = null; |
michael@0 | 176 | } |
michael@0 | 177 | |
michael@0 | 178 | this._callProgressListeners("onLocationChange", webProgress, request, location, flags); |
michael@0 | 179 | break; |
michael@0 | 180 | |
michael@0 | 181 | case "Content:SecurityChange": |
michael@0 | 182 | let [status, state] = this._fixSSLStatusAndState(json.status, json.state); |
michael@0 | 183 | |
michael@0 | 184 | if (json.isTopLevel) { |
michael@0 | 185 | // Invoking this getter triggers the generation of the underlying object, |
michael@0 | 186 | // which we need to access with ._securityUI, because .securityUI returns |
michael@0 | 187 | // a wrapper that makes _update inaccessible. |
michael@0 | 188 | void this._browser.securityUI; |
michael@0 | 189 | this._browser._securityUI._update(status, state); |
michael@0 | 190 | } |
michael@0 | 191 | |
michael@0 | 192 | this._callProgressListeners("onSecurityChange", webProgress, request, state); |
michael@0 | 193 | break; |
michael@0 | 194 | |
michael@0 | 195 | case "Content:StatusChange": |
michael@0 | 196 | this._callProgressListeners("onStatusChange", webProgress, request, json.status, json.message); |
michael@0 | 197 | break; |
michael@0 | 198 | } |
michael@0 | 199 | } |
michael@0 | 200 | }; |