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.
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 let Cc = Components.classes;
6 let Ci = Components.interfaces;
7 let Cu = Components.utils;
9 Cu.import("resource://gre/modules/Services.jsm");
10 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
11 Cu.import("resource://gre/modules/RemoteAddonsChild.jsm");
12 Cu.import("resource://gre/modules/Timer.jsm");
14 let SyncHandler = {
15 init: function() {
16 sendAsyncMessage("SetSyncHandler", {}, {handler: this});
17 },
19 getFocusedElementAndWindow: function() {
20 let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
22 let focusedWindow = {};
23 let elt = fm.getFocusedElementForWindow(content, true, focusedWindow);
24 return [elt, focusedWindow.value];
25 },
26 };
28 SyncHandler.init();
30 let WebProgressListener = {
31 init: function() {
32 let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
33 .getInterface(Ci.nsIWebProgress);
34 webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_ALL);
35 },
37 _requestSpec: function (aRequest) {
38 if (!aRequest || !(aRequest instanceof Ci.nsIChannel))
39 return null;
40 return aRequest.QueryInterface(Ci.nsIChannel).URI.spec;
41 },
43 _setupJSON: function setupJSON(aWebProgress, aRequest) {
44 return {
45 isTopLevel: aWebProgress.isTopLevel,
46 isLoadingDocument: aWebProgress.isLoadingDocument,
47 requestURI: this._requestSpec(aRequest),
48 loadType: aWebProgress.loadType,
49 documentContentType: content.document && content.document.contentType
50 };
51 },
53 _setupObjects: function setupObjects(aWebProgress) {
54 return {
55 contentWindow: content,
56 // DOMWindow is not necessarily the content-window with subframes.
57 DOMWindow: aWebProgress.DOMWindow
58 };
59 },
61 onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
62 let json = this._setupJSON(aWebProgress, aRequest);
63 let objects = this._setupObjects(aWebProgress);
65 json.stateFlags = aStateFlags;
66 json.status = aStatus;
68 sendAsyncMessage("Content:StateChange", json, objects);
69 },
71 onProgressChange: function onProgressChange(aWebProgress, aRequest, aCurSelf, aMaxSelf, aCurTotal, aMaxTotal) {
72 },
74 onLocationChange: function onLocationChange(aWebProgress, aRequest, aLocationURI, aFlags) {
75 let json = this._setupJSON(aWebProgress, aRequest);
76 let objects = this._setupObjects(aWebProgress);
78 json.location = aLocationURI ? aLocationURI.spec : "";
79 json.flags = aFlags;
81 if (json.isTopLevel) {
82 json.canGoBack = docShell.canGoBack;
83 json.canGoForward = docShell.canGoForward;
84 json.documentURI = content.document.documentURIObject.spec;
85 json.charset = content.document.characterSet;
86 }
88 sendAsyncMessage("Content:LocationChange", json, objects);
89 },
91 onStatusChange: function onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {
92 let json = this._setupJSON(aWebProgress, aRequest);
93 let objects = this._setupObjects(aWebProgress);
95 json.status = aStatus;
96 json.message = aMessage;
98 sendAsyncMessage("Content:StatusChange", json, objects);
99 },
101 onSecurityChange: function onSecurityChange(aWebProgress, aRequest, aState) {
102 let json = this._setupJSON(aWebProgress, aRequest);
103 let objects = this._setupObjects(aWebProgress);
105 json.state = aState;
106 json.status = SecurityUI.getSSLStatusAsString();
108 sendAsyncMessage("Content:SecurityChange", json, objects);
109 },
111 QueryInterface: function QueryInterface(aIID) {
112 if (aIID.equals(Ci.nsIWebProgressListener) ||
113 aIID.equals(Ci.nsISupportsWeakReference) ||
114 aIID.equals(Ci.nsISupports)) {
115 return this;
116 }
118 throw Components.results.NS_ERROR_NO_INTERFACE;
119 }
120 };
122 WebProgressListener.init();
124 let WebNavigation = {
125 _webNavigation: docShell.QueryInterface(Ci.nsIWebNavigation),
127 init: function() {
128 addMessageListener("WebNavigation:GoBack", this);
129 addMessageListener("WebNavigation:GoForward", this);
130 addMessageListener("WebNavigation:GotoIndex", this);
131 addMessageListener("WebNavigation:LoadURI", this);
132 addMessageListener("WebNavigation:Reload", this);
133 addMessageListener("WebNavigation:Stop", this);
135 // Send a CPOW for the sessionHistory object.
136 let history = this._webNavigation.sessionHistory;
137 sendAsyncMessage("WebNavigation:setHistory", {}, {history: history});
138 },
140 receiveMessage: function(message) {
141 switch (message.name) {
142 case "WebNavigation:GoBack":
143 this.goBack();
144 break;
145 case "WebNavigation:GoForward":
146 this.goForward();
147 break;
148 case "WebNavigation:GotoIndex":
149 this.gotoIndex(message.data.index);
150 break;
151 case "WebNavigation:LoadURI":
152 this.loadURI(message.data.uri, message.data.flags);
153 break;
154 case "WebNavigation:Reload":
155 this.reload(message.data.flags);
156 break;
157 case "WebNavigation:Stop":
158 this.stop(message.data.flags);
159 break;
160 }
161 },
163 goBack: function() {
164 if (this._webNavigation.canGoBack)
165 this._webNavigation.goBack();
166 },
168 goForward: function() {
169 if (this._webNavigation.canGoForward)
170 this._webNavigation.goForward();
171 },
173 gotoIndex: function(index) {
174 this._webNavigation.gotoIndex(index);
175 },
177 loadURI: function(uri, flags) {
178 this._webNavigation.loadURI(uri, flags, null, null, null);
179 },
181 reload: function(flags) {
182 this._webNavigation.reload(flags);
183 },
185 stop: function(flags) {
186 this._webNavigation.stop(flags);
187 }
188 };
190 WebNavigation.init();
192 let SecurityUI = {
193 getSSLStatusAsString: function() {
194 let status = docShell.securityUI.QueryInterface(Ci.nsISSLStatusProvider).SSLStatus;
196 if (status) {
197 let helper = Cc["@mozilla.org/network/serialization-helper;1"]
198 .getService(Ci.nsISerializationHelper);
200 status.QueryInterface(Ci.nsISerializable);
201 return helper.serializeToString(status);
202 }
204 return null;
205 }
206 };
208 let ControllerCommands = {
209 init: function () {
210 addMessageListener("ControllerCommands:Do", this);
211 },
213 receiveMessage: function(message) {
214 switch(message.name) {
215 case "ControllerCommands:Do":
216 if (docShell.isCommandEnabled(message.data))
217 docShell.doCommand(message.data);
218 break;
219 }
220 }
221 }
223 ControllerCommands.init()
225 addEventListener("DOMTitleChanged", function (aEvent) {
226 let document = content.document;
227 switch (aEvent.type) {
228 case "DOMTitleChanged":
229 if (!aEvent.isTrusted || aEvent.target.defaultView != content)
230 return;
232 sendAsyncMessage("DOMTitleChanged", { title: document.title });
233 break;
234 }
235 }, false);
237 addEventListener("DOMWindowClose", function (aEvent) {
238 if (!aEvent.isTrusted)
239 return;
240 sendAsyncMessage("DOMWindowClose");
241 aEvent.preventDefault();
242 }, false);
244 addEventListener("ImageContentLoaded", function (aEvent) {
245 if (content.document instanceof Ci.nsIImageDocument) {
246 let req = content.document.imageRequest;
247 if (!req.image)
248 return;
249 sendAsyncMessage("ImageDocumentLoaded", { width: req.image.width,
250 height: req.image.height });
251 }
252 }, false);
254 let DocumentObserver = {
255 init: function() {
256 Services.obs.addObserver(this, "document-element-inserted", false);
257 addEventListener("unload", () => {
258 Services.obs.removeObserver(this, "document-element-inserted");
259 });
260 },
262 observe: function(aSubject, aTopic, aData) {
263 if (aSubject == content.document) {
264 sendAsyncMessage("DocumentInserted", {synthetic: aSubject.mozSyntheticDocument});
265 }
266 },
267 };
268 DocumentObserver.init();
270 const ZoomManager = {
271 get fullZoom() {
272 return this._cache.fullZoom;
273 },
275 get textZoom() {
276 return this._cache.textZoom;
277 },
279 set fullZoom(value) {
280 this._cache.fullZoom = value;
281 this._markupViewer.fullZoom = value;
282 },
284 set textZoom(value) {
285 this._cache.textZoom = value;
286 this._markupViewer.textZoom = value;
287 },
289 refreshFullZoom: function() {
290 return this._refreshZoomValue('fullZoom');
291 },
293 refreshTextZoom: function() {
294 return this._refreshZoomValue('textZoom');
295 },
297 /**
298 * Retrieves specified zoom property value from markupViewer and refreshes
299 * cache if needed.
300 * @param valueName Either 'fullZoom' or 'textZoom'.
301 * @returns Returns true if cached value was actually refreshed.
302 * @private
303 */
304 _refreshZoomValue: function(valueName) {
305 let actualZoomValue = this._markupViewer[valueName];
306 if (actualZoomValue != this._cache[valueName]) {
307 this._cache[valueName] = actualZoomValue;
308 return true;
309 }
310 return false;
311 },
313 get _markupViewer() {
314 return docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer);
315 },
317 _cache: {
318 fullZoom: NaN,
319 textZoom: NaN
320 }
321 };
323 addMessageListener("FullZoom", function (aMessage) {
324 ZoomManager.fullZoom = aMessage.data.value;
325 });
327 addMessageListener("TextZoom", function (aMessage) {
328 ZoomManager.textZoom = aMessage.data.value;
329 });
331 addEventListener("FullZoomChange", function () {
332 if (ZoomManager.refreshFullZoom()) {
333 sendAsyncMessage("FullZoomChange", { value: ZoomManager.fullZoom});
334 }
335 }, false);
337 addEventListener("TextZoomChange", function (aEvent) {
338 if (ZoomManager.refreshTextZoom()) {
339 sendAsyncMessage("TextZoomChange", { value: ZoomManager.textZoom});
340 }
341 }, false);
343 RemoteAddonsChild.init(this);
345 addMessageListener("NetworkPrioritizer:AdjustPriority", (msg) => {
346 let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
347 let loadGroup = webNav.QueryInterface(Ci.nsIDocumentLoader)
348 .loadGroup.QueryInterface(Ci.nsISupportsPriority);
349 loadGroup.adjustPriority(msg.data.adjustment);
350 });
352 let AutoCompletePopup = {
353 QueryInterface: XPCOMUtils.generateQI([Ci.nsIAutoCompletePopup]),
355 init: function() {
356 // Hook up the form fill autocomplete controller.
357 let controller = Cc["@mozilla.org/satchel/form-fill-controller;1"]
358 .getService(Ci.nsIFormFillController);
360 controller.attachToBrowser(docShell, this.QueryInterface(Ci.nsIAutoCompletePopup));
362 this._input = null;
363 this._popupOpen = false;
365 addMessageListener("FormAutoComplete:HandleEnter", message => {
366 this.selectedIndex = message.data.selectedIndex;
368 let controller = Components.classes["@mozilla.org/autocomplete/controller;1"].
369 getService(Components.interfaces.nsIAutoCompleteController);
370 controller.handleEnter(message.data.isPopupSelection);
371 });
372 },
374 get input () { return this._input; },
375 get overrideValue () { return null; },
376 set selectedIndex (index) { },
377 get selectedIndex () {
378 // selectedIndex getter must be synchronous because we need the
379 // correct value when the controller is in controller::HandleEnter.
380 // We can't easily just let the parent inform us the new value every
381 // time it changes because not every action that can change the
382 // selectedIndex is trivial to catch (e.g. moving the mouse over the
383 // list).
384 return sendSyncMessage("FormAutoComplete:GetSelectedIndex", {});
385 },
386 get popupOpen () {
387 return this._popupOpen;
388 },
390 openAutocompletePopup: function (input, element) {
391 this._input = input;
392 this._popupOpen = true;
393 },
395 closePopup: function () {
396 this._popupOpen = false;
397 sendAsyncMessage("FormAutoComplete:ClosePopup", {});
398 },
400 invalidate: function () {
401 },
403 selectBy: function(reverse, page) {
404 this._index = sendSyncMessage("FormAutoComplete:SelectBy", {
405 reverse: reverse,
406 page: page
407 });
408 }
409 }
411 let [initData] = sendSyncMessage("Browser:Init");
412 docShell.useGlobalHistory = initData.useGlobalHistory;
413 if (initData.initPopup) {
414 setTimeout(function() AutoCompletePopup.init(), 0);
415 }