From 3fde9c91241fed39c1d1122135212143d38e0527 Mon Sep 17 00:00:00 2001 From: Shane Caraveo Date: Wed, 5 Nov 2014 17:22:27 -0800 Subject: [PATCH] Bug 915547 fix activation in e10s windows, r=markh --- browser/base/content/browser-social.js | 169 ++++++++---------- browser/base/content/browser.js | 2 +- browser/base/content/content.js | 35 ++++ browser/base/content/test/social/browser.ini | 15 +- .../content/test/social/browser_addons.js | 24 ++- .../content/test/social/browser_blocklist.js | 8 +- .../test/social/browser_social_activation.js | 16 +- .../test/social/browser_social_marks.js | 27 ++- .../test/social/browser_social_status.js | 17 +- .../content/test/social/social_activate.html | 5 - browser/modules/Social.jsm | 4 +- toolkit/components/social/SocialService.jsm | 70 +++----- 12 files changed, 215 insertions(+), 177 deletions(-) diff --git a/browser/base/content/browser-social.js b/browser/base/content/browser-social.js index 567fec817cc4..c7dee4758480 100644 --- a/browser/base/content/browser-social.js +++ b/browser/base/content/browser-social.js @@ -8,7 +8,8 @@ let SocialUI, SocialMarks, SocialShare, SocialSidebar, - SocialStatus; + SocialStatus, + SocialActivationListener; (function() { @@ -70,8 +71,8 @@ SocialUI = { Services.prefs.addObserver("social.toast-notifications.enabled", this, false); - gBrowser.addEventListener("ActivateSocialFeature", this._activationEventHandler.bind(this), true, true); CustomizableUI.addListener(this); + SocialActivationListener.init(); // menupopups that list social providers. we only populate them when shown, // and if it has not been done already. @@ -105,6 +106,7 @@ SocialUI = { Services.prefs.removeObserver("social.toast-notifications.enabled", this); CustomizableUI.removeListener(this); + SocialActivationListener.uninit(); document.getElementById("viewSidebarMenu").removeEventListener("popupshowing", SocialSidebar.populateSidebarMenu, true); document.getElementById("social-statusarea-popup").removeEventListener("popupshowing", SocialSidebar.populateSidebarMenu, true); @@ -171,95 +173,6 @@ SocialUI = { SocialMarks.populateToolbarPalette(); }, - // This handles "ActivateSocialFeature" events fired against content documents - // in this window. If this activation happens from within Firefox, such as - // about:home or the share panel, we bypass the enable prompt. Any website - // activation, such as from the activations directory or a providers website - // will still get the prompt. - _activationEventHandler: function SocialUI_activationHandler(e, options={}) { - let targetDoc; - let node; - if (e.target instanceof HTMLDocument) { - // version 0 support - targetDoc = e.target; - node = targetDoc.documentElement - } else { - targetDoc = e.target.ownerDocument; - node = e.target; - } - if (!(targetDoc instanceof HTMLDocument)) - return; - - // The share panel iframe will not match "content" so it passes a bypass - // flag - if (!options.bypassContentCheck && targetDoc.defaultView != content) - return; - - // If we are in PB mode, we silently do nothing (bug 829404 exists to - // do something sensible here...) - if (PrivateBrowsingUtils.isWindowPrivate(window)) - return; - - // If the last event was received < 1s ago, ignore this one - let now = Date.now(); - if (now - Social.lastEventReceived < 1000) - return; - Social.lastEventReceived = now; - - // We only want to activate if it is as a result of user input. - let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - if (!dwu.isHandlingUserInput) { - Cu.reportError("attempt to activate provider without user input from " + targetDoc.nodePrincipal.origin); - return; - } - - let data = node.getAttribute("data-service"); - if (data) { - try { - data = JSON.parse(data); - } catch(e) { - Cu.reportError("Social Service manifest parse error: "+e); - return; - } - } - Social.installProvider(targetDoc, data, function(manifest) { - Social.activateFromOrigin(manifest.origin, function(provider) { - if (provider.sidebarURL) { - SocialSidebar.show(provider.origin); - } - if (provider.shareURL) { - // Ensure that the share button is somewhere usable. - // SocialShare.shareButton may return null if it is in the menu-panel - // and has never been visible, so we check the widget directly. If - // there is no area for the widget we move it into the toolbar. - let widget = CustomizableUI.getWidget("social-share-button"); - if (!widget.areaType) { - CustomizableUI.addWidgetToArea("social-share-button", CustomizableUI.AREA_NAVBAR); - // ensure correct state - SocialUI.onCustomizeEnd(window); - } - - // make this new provider the selected provider. If the panel hasn't - // been opened, we need to make the frame first. - SocialShare._createFrame(); - SocialShare.iframe.setAttribute('src', 'data:text/plain;charset=utf8,'); - SocialShare.iframe.setAttribute('origin', provider.origin); - // get the right button selected - SocialShare.populateProviderMenu(); - if (SocialShare.panel.state == "open") { - SocialShare.sharePage(provider.origin); - } - } - if (provider.postActivationURL) { - // if activated from an open share panel, we load the landing page in - // a background tab - gBrowser.loadOneTab(provider.postActivationURL, {inBackground: SocialShare.panel.state == "open"}); - } - }); - }, options); - }, - showLearnMore: function() { let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "social-api"; openUILinkIn(url, "tab"); @@ -353,6 +266,68 @@ SocialUI = { } } +// message manager handlers +SocialActivationListener = { + init: function() { + messageManager.addMessageListener("Social:Activation", this); + }, + uninit: function() { + messageManager.removeMessageListener("Social:Activation", this); + }, + receiveMessage: function(aMessage) { + let data = aMessage.json; + let browser = aMessage.target; + data.window = window; + // if the source if the message is the share panel, we do a one-click + // installation. The source of activations is controlled by the + // social.directories preference + let options; + if (browser == SocialShare.iframe && Services.prefs.getBoolPref("social.share.activationPanelEnabled")) { + options = { bypassContentCheck: true, bypassInstallPanel: true }; + } + + // If we are in PB mode, we silently do nothing (bug 829404 exists to + // do something sensible here...) + if (PrivateBrowsingUtils.isWindowPrivate(window)) + return; + Social.installProvider(data, function(manifest) { + Social.activateFromOrigin(manifest.origin, function(provider) { + if (provider.sidebarURL) { + SocialSidebar.show(provider.origin); + } + if (provider.shareURL) { + // Ensure that the share button is somewhere usable. + // SocialShare.shareButton may return null if it is in the menu-panel + // and has never been visible, so we check the widget directly. If + // there is no area for the widget we move it into the toolbar. + let widget = CustomizableUI.getWidget("social-share-button"); + if (!widget.areaType) { + CustomizableUI.addWidgetToArea("social-share-button", CustomizableUI.AREA_NAVBAR); + // ensure correct state + SocialUI.onCustomizeEnd(window); + } + + // make this new provider the selected provider. If the panel hasn't + // been opened, we need to make the frame first. + SocialShare._createFrame(); + SocialShare.iframe.setAttribute('src', 'data:text/plain;charset=utf8,'); + SocialShare.iframe.setAttribute('origin', provider.origin); + // get the right button selected + SocialShare.populateProviderMenu(); + if (SocialShare.panel.state == "open") { + SocialShare.sharePage(provider.origin); + } + } + if (provider.postActivationURL) { + // if activated from an open share panel, we load the landing page in + // a background tab + gBrowser.loadOneTab(provider.postActivationURL, {inBackground: SocialShare.panel.state == "open"}); + } + }); + }, options); + } +} + SocialFlyout = { get panel() { return document.getElementById("social-flyout-panel"); @@ -514,15 +489,8 @@ SocialShare = { return this.panel.lastChild; }, - _activationHandler: function(event) { - if (!Services.prefs.getBoolPref("social.share.activationPanelEnabled")) - return; - SocialUI._activationEventHandler(event, { bypassContentCheck: true, bypassInstallPanel: true }); - }, - uninit: function () { if (this.iframe) { - this.iframe.removeEventListener("ActivateSocialFeature", this._activationHandler, true, true); this.iframe.remove(); } }, @@ -541,7 +509,10 @@ SocialShare = { iframe.setAttribute("disableglobalhistory", "true"); iframe.setAttribute("flex", "1"); panel.appendChild(iframe); - this.iframe.addEventListener("ActivateSocialFeature", this._activationHandler, true, true); + iframe.addEventListener("DOMContentLoaded", function _firstload() { + iframe.removeEventListener("DOMContentLoaded", _firstload, true); + iframe.messageManager.loadFrameScript("chrome://browser/content/content.js", true); + }, true); this.populateProviderMenu(); }, diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index c10af3b1ff4b..2c897539d110 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -3972,7 +3972,7 @@ var XULBrowserWindow = { .chromeEventHandler; // Ignore loads that aren't in the main tabbrowser - if (browser.localName != "browser" || browser.getTabBrowser() != gBrowser) + if (browser.localName != "browser" || !browser.getTabBrowser || browser.getTabBrowser() != gBrowser) return true; if (!E10SUtils.shouldLoadURI(aDocShell, aURI, aReferrer)) { diff --git a/browser/base/content/content.js b/browser/base/content/content.js index 18081369a0c9..c91ab226c9a8 100644 --- a/browser/base/content/content.js +++ b/browser/base/content/content.js @@ -837,6 +837,41 @@ addEventListener("pageshow", function(event) { } }); +addEventListener("ActivateSocialFeature", function (aEvent) { + let document = content.document; + if (PrivateBrowsingUtils.isContentWindowPrivate(content)) { + Cu.reportError("cannot use social providers in private windows"); + return; + } + let dwu = content.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + if (!dwu.isHandlingUserInput) { + Cu.reportError("attempt to activate provider without user input from " + document.nodePrincipal.origin); + return; + } + + let node = aEvent.target; + let ownerDocument = node.ownerDocument; + let data = node.getAttribute("data-service"); + if (data) { + try { + data = JSON.parse(data); + } catch(e) { + Cu.reportError("Social Service manifest parse error: " + e); + return; + } + } else { + Cu.reportError("Social Service manifest not available"); + return; + } + + sendAsyncMessage("Social:Activation", { + url: ownerDocument.location.href, + origin: ownerDocument.nodePrincipal.origin, + manifest: data + }); +}, true, true); + addMessageListener("ContextMenu:SaveVideoFrameAsImage", (message) => { let video = message.objects.target; let canvas = content.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); diff --git a/browser/base/content/test/social/browser.ini b/browser/base/content/test/social/browser.ini index 65be870c962e..c115706025bc 100644 --- a/browser/base/content/test/social/browser.ini +++ b/browser/base/content/test/social/browser.ini @@ -27,34 +27,29 @@ support-files = unchecked.jpg [browser_aboutHome_activation.js] -skip-if = e10s # Bug 915547 (social providers don't install) +skip-if = e10s # Bug 1053965 "cw.ensureSnippetsMapThen is not a function", also see general/browser.ini about:home comments [browser_addons.js] -skip-if = e10s # Bug 915547 (social providers don't install) [browser_blocklist.js] -skip-if = e10s # Bug 915547 (social providers don't install) [browser_share.js] -skip-if = e10s # Bug 915547 (social providers don't install) +skip-if = e10s # Bug 1053973 (OpenGraphBuilder) [browser_social_activation.js] -skip-if = e10s # Bug 915547 (social providers don't install) +skip-if = e10s # Bug 933103 synthesizeMouseAtCenter not e10s friendly [browser_social_chatwindow.js] -skip-if = e10s # Bug 915547 (social providers don't install) [browser_social_chatwindow_resize.js] -skip-if = e10s # Bug 915547 (social providers don't install) [browser_social_chatwindowfocus.js] -skip-if = e10s # Bug 915547 (social providers don't install) +skip-if = e10s # tab crash on data url used in this test [browser_social_errorPage.js] [browser_social_flyout.js] skip-if = e10s # when we backed out bug 1047603, this test broke. [browser_social_isVisible.js] [browser_social_marks.js] -skip-if = e10s # Bug 915547 (social providers don't install) +skip-if = e10s # Bug 1053973 (OpenGraphBuilder) [browser_social_multiprovider.js] skip-if = e10s # Bug 1069162 - lots of orange [browser_social_multiworker.js] [browser_social_perwindowPB.js] [browser_social_sidebar.js] [browser_social_status.js] -skip-if = e10s # Bug 915547 (social providers don't install) [browser_social_window.js] [browser_social_workercrash.js] #skip-if = !crashreporter diff --git a/browser/base/content/test/social/browser_addons.js b/browser/base/content/test/social/browser_addons.js index 4f6965b7445b..9f424def0a7a 100644 --- a/browser/base/content/test/social/browser_addons.js +++ b/browser/base/content/test/social/browser_addons.js @@ -193,7 +193,13 @@ var tests = { let installFrom = doc.nodePrincipal.origin; Services.prefs.setCharPref("social.whitelist", ""); is(SocialService.getOriginActivationType(installFrom), "foreign", "testing foriegn install"); - Social.installProvider(doc, manifest2, function(addonManifest) { + let data = { + origin: doc.nodePrincipal.origin, + url: doc.location.href, + manifest: manifest2, + window: window + } + Social.installProvider(data, function(addonManifest) { Services.prefs.clearUserPref("social.whitelist"); SocialService.enableProvider(addonManifest.origin, function(provider) { Social.uninstallProvider(addonManifest.origin); @@ -217,7 +223,13 @@ var tests = { let installFrom = doc.nodePrincipal.origin; Services.prefs.setCharPref("social.directories", installFrom); is(SocialService.getOriginActivationType(installFrom), "directory", "testing directory install"); - Social.installProvider(doc, manifest2, function(addonManifest) { + let data = { + origin: installFrom, + url: doc.location.href, + manifest: manifest2, + window: window + } + Social.installProvider(data, function(addonManifest) { Services.prefs.clearUserPref("social.directories"); SocialService.enableProvider(addonManifest.origin, function(provider) { Social.uninstallProvider(addonManifest.origin); @@ -241,7 +253,13 @@ var tests = { let doc = tab.linkedBrowser.contentDocument; let installFrom = doc.nodePrincipal.origin; Services.prefs.setCharPref("social.whitelist", installFrom); - Social.installProvider(doc, manifest2, function(addonManifest) { + let data = { + origin: installFrom, + url: doc.location.href, + manifest: manifest2, + window: window + } + Social.installProvider(data, function(addonManifest) { SocialService.enableProvider(addonManifest.origin, function(provider) { is(provider.manifest.version, 1, "manifest version is 1"); diff --git a/browser/base/content/test/social/browser_blocklist.js b/browser/base/content/test/social/browser_blocklist.js index 575346384e27..eea8ce2cc334 100644 --- a/browser/base/content/test/social/browser_blocklist.js +++ b/browser/base/content/test/social/browser_blocklist.js @@ -113,7 +113,13 @@ var tests = { try { // expecting an exception when attempting to install a hard blocked // provider - Social.installProvider(doc, manifest_bad, function(addonManifest) { + let data = { + origin: doc.nodePrincipal.origin, + url: doc.location.href, + manifest: manifest_bad, + window: window + } + Social.installProvider(data, function(addonManifest) { gBrowser.removeTab(tab); finishTest(false); }); diff --git a/browser/base/content/test/social/browser_social_activation.js b/browser/base/content/test/social/browser_social_activation.js index 57c50a52ea23..48666160c6de 100644 --- a/browser/base/content/test/social/browser_social_activation.js +++ b/browser/base/content/test/social/browser_social_activation.js @@ -86,9 +86,6 @@ function activateIFrameProvider(domain, callback) { } function waitForProviderLoad(cb) { - Services.obs.addObserver(function providerSet(subject, topic, data) { - Services.obs.removeObserver(providerSet, "social:provider-enabled"); - info("social:provider-enabled observer was notified"); waitForCondition(function() { let sbrowser = document.getElementById("social-sidebar-browser"); let provider = SocialSidebar.provider; @@ -104,7 +101,6 @@ function waitForProviderLoad(cb) { executeSoon(cb); }, "waitForProviderLoad: provider profile was not set"); - }, "social:provider-enabled", false); } @@ -149,14 +145,15 @@ function activateOneProvider(manifest, finishActivation, aCallback) { let panel = document.getElementById("servicesInstall-notification"); PopupNotifications.panel.addEventListener("popupshown", function onpopupshown() { PopupNotifications.panel.removeEventListener("popupshown", onpopupshown); - info("servicesInstall-notification panel opened"); + ok(!panel.hidden, "servicesInstall-notification panel opened"); if (finishActivation) panel.button.click(); else panel.closebutton.click(); }); - - activateProvider(manifest.origin, function() { + PopupNotifications.panel.addEventListener("popuphidden", function _hidden() { + PopupNotifications.panel.removeEventListener("popuphidden", _hidden); + ok(panel.hidden, "servicesInstall-notification panel hidden"); if (!finishActivation) { ok(panel.hidden, "activation panel is not showing"); executeSoon(aCallback); @@ -169,6 +166,11 @@ function activateOneProvider(manifest, finishActivation, aCallback) { }); } }); + + // the test will continue as the popup events fire... + activateProvider(manifest.origin, function() { + info("waiting on activation panel to open/close..."); + }); } let gTestDomains = ["https://example.com", "https://test1.example.com", "https://test2.example.com"]; diff --git a/browser/base/content/test/social/browser_social_marks.js b/browser/base/content/test/social/browser_social_marks.js index 139d5e6877f6..fa80786189df 100644 --- a/browser/base/content/test/social/browser_social_marks.js +++ b/browser/base/content/test/social/browser_social_marks.js @@ -105,7 +105,14 @@ var tests = { let activationURL = manifest3.origin + "/browser/browser/base/content/test/social/social_activate.html" addTab(activationURL, function(tab) { let doc = tab.linkedBrowser.contentDocument; - Social.installProvider(doc, manifest3, function(addonManifest) { + let data = { + origin: doc.nodePrincipal.origin, + url: doc.location.href, + manifest: manifest3, + window: window + } + + Social.installProvider(data, function(addonManifest) { // enable the provider so we know the button would have appeared SocialService.enableProvider(manifest3.origin, function(provider) { is(provider.origin, manifest3.origin, "provider is installed"); @@ -133,7 +140,14 @@ var tests = { let activationURL = manifest2.origin + "/browser/browser/base/content/test/social/social_activate.html" addTab(activationURL, function(tab) { let doc = tab.linkedBrowser.contentDocument; - Social.installProvider(doc, manifest2, function(addonManifest) { + let data = { + origin: doc.nodePrincipal.origin, + url: doc.location.href, + manifest: manifest2, + window: window + } + + Social.installProvider(data, function(addonManifest) { SocialService.enableProvider(manifest2.origin, function(provider) { is(provider.origin, manifest2.origin, "provider is installed"); let id = SocialMarks._toolbarHelper.idFromOrigin(manifest2.origin); @@ -379,7 +393,14 @@ var tests = { let toolbar = document.getElementById("nav-bar"); addTab(activationURL, function(tab) { let doc = tab.linkedBrowser.contentDocument; - Social.installProvider(doc, manifest, function(addonManifest) { + let data = { + origin: doc.nodePrincipal.origin, + url: doc.location.href, + manifest: manifest, + window: window + } + + Social.installProvider(data, function(addonManifest) { // enable the provider so we know the button would have appeared SocialService.enableProvider(manifest.origin, function(provider) { waitForCondition(function() { return CustomizableUI.getWidget(id) }, diff --git a/browser/base/content/test/social/browser_social_status.js b/browser/base/content/test/social/browser_social_status.js index 77fa52b2007a..9a1bd6615aaf 100644 --- a/browser/base/content/test/social/browser_social_status.js +++ b/browser/base/content/test/social/browser_social_status.js @@ -66,7 +66,13 @@ var tests = { let activationURL = manifest3.origin + "/browser/browser/base/content/test/social/social_activate.html" addTab(activationURL, function(tab) { let doc = tab.linkedBrowser.contentDocument; - Social.installProvider(doc, manifest3, function(addonManifest) { + let data = { + origin: doc.nodePrincipal.origin, + url: doc.location.href, + manifest: manifest3, + window: window + } + Social.installProvider(data, function(addonManifest) { // enable the provider so we know the button would have appeared SocialService.enableProvider(manifest3.origin, function(provider) { is(provider.origin, manifest3.origin, "provider is installed"); @@ -93,7 +99,14 @@ var tests = { let activationURL = manifest2.origin + "/browser/browser/base/content/test/social/social_activate.html" addTab(activationURL, function(tab) { let doc = tab.linkedBrowser.contentDocument; - Social.installProvider(doc, manifest2, function(addonManifest) { + let data = { + origin: doc.nodePrincipal.origin, + url: doc.location.href, + manifest: manifest2, + window: window + } + + Social.installProvider(data, function(addonManifest) { SocialService.enableProvider(manifest2.origin, function(provider) { is(provider.origin, manifest2.origin, "provider is installed"); let id = SocialStatus._toolbarHelper.idFromOrigin(manifest2.origin); diff --git a/browser/base/content/test/social/social_activate.html b/browser/base/content/test/social/social_activate.html index 59cd8aa09484..c2c0ced58eb4 100644 --- a/browser/base/content/test/social/social_activate.html +++ b/browser/base/content/test/social/social_activate.html @@ -31,16 +31,11 @@ function activate(node) { node.dispatchEvent(event); } -function oldActivate(node) { - var event = new CustomEvent("ActivateSocialFeature"); - document.dispatchEvent(event); -} nothing to see here - diff --git a/browser/modules/Social.jsm b/browser/modules/Social.jsm index 822b17892f29..c39bf51bb50f 100644 --- a/browser/modules/Social.jsm +++ b/browser/modules/Social.jsm @@ -169,8 +169,8 @@ this.Social = { return SocialService.getManifestByOrigin(origin); }, - installProvider: function(doc, data, installCallback, aBypassUserEnable=false) { - SocialService.installProvider(doc, data, installCallback, aBypassUserEnable); + installProvider: function(data, installCallback, options={}) { + SocialService.installProvider(data, installCallback, options); }, uninstallProvider: function(origin, aCallback) { diff --git a/toolkit/components/social/SocialService.jsm b/toolkit/components/social/SocialService.jsm index df127648e596..c5aaab7fdec9 100644 --- a/toolkit/components/social/SocialService.jsm +++ b/toolkit/components/social/SocialService.jsm @@ -500,7 +500,7 @@ this.SocialService = { } }, - _manifestFromData: function(type, data, principal) { + _manifestFromData: function(type, data, installOrigin) { let featureURLs = ['workerURL', 'sidebarURL', 'shareURL', 'statusURL', 'markURL']; let resolveURLs = featureURLs.concat(['postActivationURL']); @@ -510,10 +510,11 @@ this.SocialService = { Cu.reportError("SocialService.manifestFromData directory service provided manifest without origin."); return null; } - let URI = Services.io.newURI(data.origin, null, null); - principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(URI); + installOrigin = data.origin; } // force/fixup origin + let URI = Services.io.newURI(installOrigin, null, null); + principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(URI); data.origin = principal.origin; // iconURL and name are required @@ -544,26 +545,13 @@ this.SocialService = { return data; }, - _getChromeWindow: function(aWindow) { - var chromeWin = aWindow - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShellTreeItem) - .rootTreeItem - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindow) - .QueryInterface(Ci.nsIDOMChromeWindow); - return chromeWin; - }, - - _showInstallNotification: function(aDOMDocument, aAddonInstaller) { + _showInstallNotification: function(data, aAddonInstaller) { let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties"); let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties"); - let requestingWindow = aDOMDocument.defaultView.top; - let chromeWin = this._getChromeWindow(requestingWindow).wrappedJSObject; - let browser = chromeWin.gBrowser.getBrowserForDocument(aDOMDocument); - let requestingURI = Services.io.newURI(aAddonInstaller.addon.manifest.origin, null, null); + // internal activation does not have a host, use the manifest origin in that case + let requestingURI = Services.io.newURI(data.installType == "internal" ? + data.manifest.origin : data.url, null, null); let productName = brandBundle.GetStringFromName("brandShortName"); let message = browserBundle.formatStringFromName("service.install.description", @@ -582,37 +570,34 @@ this.SocialService = { }; let anchor = "servicesInstall-notification-icon"; let notificationid = "servicesInstall"; - chromeWin.PopupNotifications.show(browser, notificationid, message, anchor, - action, [], options); + data.window.PopupNotifications.show(data.window.gBrowser.selectedBrowser, + notificationid, message, anchor, + action, [], options); }, - installProvider: function(aDOMDocument, data, installCallback, options={}) { - let manifest; - let installOrigin = aDOMDocument.nodePrincipal.origin; - - let installType = getOriginActivationType(installOrigin); + installProvider: function(data, installCallback, options={}) { + data.installType = getOriginActivationType(data.origin); // if we get data, we MUST have a valid manifest generated from the data - manifest = this._manifestFromData(installType, data, aDOMDocument.nodePrincipal); + let manifest = this._manifestFromData(data.installType, data.manifest, data.origin); if (!manifest) - throw new Error("SocialService.installProvider: service configuration is invalid from " + aDOMDocument.location.href); + throw new Error("SocialService.installProvider: service configuration is invalid from " + data.url); let addon = new AddonWrapper(manifest); if (addon && addon.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED) throw new Error("installProvider: provider with origin [" + - installOrigin + "] is blocklisted"); + data.origin + "] is blocklisted"); // manifestFromData call above will enforce correct origin. To support // activation from about: uris, we need to be sure to use the updated // origin on the manifest. - installOrigin = manifest.origin; - - let id = getAddonIDFromOrigin(installOrigin); + data.manifest = manifest; + let id = getAddonIDFromOrigin(manifest.origin); AddonManager.getAddonByID(id, function(aAddon) { if (aAddon && aAddon.userDisabled) { aAddon.cancelUninstall(); aAddon.userDisabled = false; } schedule(function () { - this._installProvider(aDOMDocument, manifest, options, aManifest => { + this._installProvider(data, options, aManifest => { this._notifyProviderListeners("provider-installed", aManifest.origin); installCallback(aManifest); }); @@ -620,21 +605,20 @@ this.SocialService = { }.bind(this)); }, - _installProvider: function(aDOMDocument, manifest, options, installCallback) { - if (!manifest) + _installProvider: function(data, options, installCallback) { + if (!data.manifest) throw new Error("Cannot install provider without manifest data"); - let installType = getOriginActivationType(aDOMDocument.nodePrincipal.origin); - if (installType == "foreign" && !Services.prefs.getBoolPref("social.remote-install.enabled")) + if (data.installType == "foreign" && !Services.prefs.getBoolPref("social.remote-install.enabled")) throw new Error("Remote install of services is disabled"); - let installer = new AddonInstaller(aDOMDocument.location.href, manifest, installCallback); + let installer = new AddonInstaller(data.url, data.manifest, installCallback); let bypassPanel = options.bypassInstallPanel || - (installType == "internal" && manifest.oneclick); + (data.installType == "internal" && data.manifest.oneclick); if (bypassPanel) installer.install(); else - this._showInstallNotification(aDOMDocument, installer); + this._showInstallNotification(data, installer); }, createWrapper: function(manifest) { @@ -647,11 +631,9 @@ this.SocialService = { * the front end to deal with any reload. */ updateProvider: function(aUpdateOrigin, aManifest) { - let originUri = Services.io.newURI(aUpdateOrigin, null, null); - let principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(originUri); let installType = this.getOriginActivationType(aUpdateOrigin); // if we get data, we MUST have a valid manifest generated from the data - let manifest = this._manifestFromData(installType, aManifest, principal); + let manifest = this._manifestFromData(installType, aManifest, aUpdateOrigin); if (!manifest) throw new Error("SocialService.installProvider: service configuration is invalid from " + aUpdateOrigin);