Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: JavaScript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* vim: set ts=2 et sw=2 tw=80: */ |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | "use strict"; |
michael@0 | 8 | |
michael@0 | 9 | const {classes: Cc, interfaces: Ci, utils: Cu} = Components; |
michael@0 | 10 | Cu.import("resource://gre/modules/Services.jsm"); |
michael@0 | 11 | Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
michael@0 | 12 | |
michael@0 | 13 | XPCOMUtils.defineLazyModuleGetter(this, "getFrameWorkerHandle", "resource://gre/modules/FrameWorker.jsm"); |
michael@0 | 14 | XPCOMUtils.defineLazyModuleGetter(this, "openChatWindow", "resource://gre/modules/MozSocialAPI.jsm"); |
michael@0 | 15 | |
michael@0 | 16 | this.EXPORTED_SYMBOLS = ["WorkerAPI"]; |
michael@0 | 17 | |
michael@0 | 18 | this.WorkerAPI = function WorkerAPI(provider, port) { |
michael@0 | 19 | if (!port) |
michael@0 | 20 | throw new Error("Can't initialize WorkerAPI with a null port"); |
michael@0 | 21 | |
michael@0 | 22 | this._provider = provider; |
michael@0 | 23 | this._port = port; |
michael@0 | 24 | this._port.onmessage = this._handleMessage.bind(this); |
michael@0 | 25 | |
michael@0 | 26 | // Send an "intro" message so the worker knows this is the port |
michael@0 | 27 | // used for the api. |
michael@0 | 28 | // later we might even include an API version - version 0 for now! |
michael@0 | 29 | this._port.postMessage({topic: "social.initialize"}); |
michael@0 | 30 | } |
michael@0 | 31 | |
michael@0 | 32 | WorkerAPI.prototype = { |
michael@0 | 33 | terminate: function terminate() { |
michael@0 | 34 | this._port.close(); |
michael@0 | 35 | }, |
michael@0 | 36 | |
michael@0 | 37 | _handleMessage: function _handleMessage(event) { |
michael@0 | 38 | let {topic, data} = event.data; |
michael@0 | 39 | let handler = this.handlers[topic]; |
michael@0 | 40 | if (!handler) { |
michael@0 | 41 | Cu.reportError("WorkerAPI: topic doesn't have a handler: '" + topic + "'"); |
michael@0 | 42 | return; |
michael@0 | 43 | } |
michael@0 | 44 | try { |
michael@0 | 45 | handler.call(this, data); |
michael@0 | 46 | } catch (ex) { |
michael@0 | 47 | Cu.reportError("WorkerAPI: failed to handle message '" + topic + "': " + ex + "\n" + ex.stack); |
michael@0 | 48 | } |
michael@0 | 49 | }, |
michael@0 | 50 | |
michael@0 | 51 | handlers: { |
michael@0 | 52 | "social.manifest-get": function(data) { |
michael@0 | 53 | // retreive the currently installed manifest from firefox |
michael@0 | 54 | this._port.postMessage({topic: "social.manifest", data: this._provider.manifest}); |
michael@0 | 55 | }, |
michael@0 | 56 | "social.manifest-set": function(data) { |
michael@0 | 57 | // the provider will get reloaded as a result of this call |
michael@0 | 58 | let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService; |
michael@0 | 59 | let origin = this._provider.origin; |
michael@0 | 60 | SocialService.updateProvider(origin, data); |
michael@0 | 61 | }, |
michael@0 | 62 | "social.reload-worker": function(data) { |
michael@0 | 63 | this._provider.reload(); |
michael@0 | 64 | }, |
michael@0 | 65 | "social.user-profile": function (data) { |
michael@0 | 66 | this._provider.updateUserProfile(data); |
michael@0 | 67 | }, |
michael@0 | 68 | "social.ambient-notification": function (data) { |
michael@0 | 69 | this._provider.setAmbientNotification(data); |
michael@0 | 70 | }, |
michael@0 | 71 | "social.cookies-get": function(data) { |
michael@0 | 72 | // We don't want to trust provider.origin etc, just incase the provider |
michael@0 | 73 | // redirected away or something else bad is going on. So we want to |
michael@0 | 74 | // reach into the Worker's document and fetch the actual cookies it has. |
michael@0 | 75 | // We need to do this via our own message dance. |
michael@0 | 76 | let port = this._port; |
michael@0 | 77 | let whandle = getFrameWorkerHandle(this._provider.workerURL, null); |
michael@0 | 78 | whandle.port.close(); |
michael@0 | 79 | whandle._worker.browserPromise.then(browser => { |
michael@0 | 80 | let mm = browser.messageManager; |
michael@0 | 81 | mm.addMessageListener("frameworker:cookie-get-response", function _onCookieResponse(msg) { |
michael@0 | 82 | mm.removeMessageListener("frameworker:cookie-get-response", _onCookieResponse); |
michael@0 | 83 | let cookies = msg.json.split(";"); |
michael@0 | 84 | let results = []; |
michael@0 | 85 | cookies.forEach(function(aCookie) { |
michael@0 | 86 | let [name, value] = aCookie.split("="); |
michael@0 | 87 | if (name || value) { |
michael@0 | 88 | results.push({name: unescape(name.trim()), |
michael@0 | 89 | value: value ? unescape(value.trim()) : ""}); |
michael@0 | 90 | } |
michael@0 | 91 | }); |
michael@0 | 92 | port.postMessage({topic: "social.cookies-get-response", |
michael@0 | 93 | data: results}); |
michael@0 | 94 | }); |
michael@0 | 95 | mm.sendAsyncMessage("frameworker:cookie-get"); |
michael@0 | 96 | }); |
michael@0 | 97 | }, |
michael@0 | 98 | 'social.request-chat': function(data) { |
michael@0 | 99 | openChatWindow(null, this._provider, data); |
michael@0 | 100 | }, |
michael@0 | 101 | 'social.notification-create': function(data) { |
michael@0 | 102 | if (!Services.prefs.getBoolPref("social.toast-notifications.enabled")) |
michael@0 | 103 | return; |
michael@0 | 104 | |
michael@0 | 105 | let port = this._port; |
michael@0 | 106 | let provider = this._provider; |
michael@0 | 107 | let {id, type, icon, body, action, actionArgs} = data; |
michael@0 | 108 | let alertsService = Cc["@mozilla.org/alerts-service;1"] |
michael@0 | 109 | .getService(Ci.nsIAlertsService); |
michael@0 | 110 | function listener(subject, topic, data) { |
michael@0 | 111 | if (topic === "alertclickcallback") { |
michael@0 | 112 | // we always post back the click |
michael@0 | 113 | port.postMessage({topic: "social.notification-action", |
michael@0 | 114 | data: {id: id, |
michael@0 | 115 | action: action, |
michael@0 | 116 | actionArgs: actionArgs}}); |
michael@0 | 117 | switch (action) { |
michael@0 | 118 | case "link": |
michael@0 | 119 | // if there is a url, make it open a tab |
michael@0 | 120 | if (actionArgs.toURL) { |
michael@0 | 121 | let uriToOpen = provider.resolveUri(actionArgs.toURL); |
michael@0 | 122 | // Bug 815970 - facebook gives us http:// links even though |
michael@0 | 123 | // the origin is https:// - so we perform a fixup here. |
michael@0 | 124 | let pUri = Services.io.newURI(provider.origin, null, null); |
michael@0 | 125 | if (uriToOpen.scheme != pUri.scheme) |
michael@0 | 126 | uriToOpen.scheme = pUri.scheme; |
michael@0 | 127 | if (provider.isSameOrigin(uriToOpen)) { |
michael@0 | 128 | let xulWindow = Services.wm.getMostRecentWindow("navigator:browser"); |
michael@0 | 129 | xulWindow.openUILinkIn(uriToOpen.spec, "tab"); |
michael@0 | 130 | } else { |
michael@0 | 131 | Cu.reportError("Not opening notification link " + actionArgs.toURL |
michael@0 | 132 | + " as not in provider origin"); |
michael@0 | 133 | } |
michael@0 | 134 | } |
michael@0 | 135 | break; |
michael@0 | 136 | default: |
michael@0 | 137 | break; |
michael@0 | 138 | } |
michael@0 | 139 | } |
michael@0 | 140 | } |
michael@0 | 141 | alertsService.showAlertNotification(icon, |
michael@0 | 142 | this._provider.name, // title |
michael@0 | 143 | body, |
michael@0 | 144 | !!action, // text clickable if an |
michael@0 | 145 | // action was provided. |
michael@0 | 146 | null, |
michael@0 | 147 | listener, |
michael@0 | 148 | type); |
michael@0 | 149 | }, |
michael@0 | 150 | } |
michael@0 | 151 | } |