Bug 915547 fix activation in e10s windows, r=markh

This commit is contained in:
Shane Caraveo 2014-11-05 17:22:27 -08:00
Родитель c936429261
Коммит 3fde9c9124
12 изменённых файлов: 215 добавлений и 177 удалений

Просмотреть файл

@ -8,7 +8,8 @@ let SocialUI,
SocialMarks, SocialMarks,
SocialShare, SocialShare,
SocialSidebar, SocialSidebar,
SocialStatus; SocialStatus,
SocialActivationListener;
(function() { (function() {
@ -70,8 +71,8 @@ SocialUI = {
Services.prefs.addObserver("social.toast-notifications.enabled", this, false); Services.prefs.addObserver("social.toast-notifications.enabled", this, false);
gBrowser.addEventListener("ActivateSocialFeature", this._activationEventHandler.bind(this), true, true);
CustomizableUI.addListener(this); CustomizableUI.addListener(this);
SocialActivationListener.init();
// menupopups that list social providers. we only populate them when shown, // menupopups that list social providers. we only populate them when shown,
// and if it has not been done already. // and if it has not been done already.
@ -105,6 +106,7 @@ SocialUI = {
Services.prefs.removeObserver("social.toast-notifications.enabled", this); Services.prefs.removeObserver("social.toast-notifications.enabled", this);
CustomizableUI.removeListener(this); CustomizableUI.removeListener(this);
SocialActivationListener.uninit();
document.getElementById("viewSidebarMenu").removeEventListener("popupshowing", SocialSidebar.populateSidebarMenu, true); document.getElementById("viewSidebarMenu").removeEventListener("popupshowing", SocialSidebar.populateSidebarMenu, true);
document.getElementById("social-statusarea-popup").removeEventListener("popupshowing", SocialSidebar.populateSidebarMenu, true); document.getElementById("social-statusarea-popup").removeEventListener("popupshowing", SocialSidebar.populateSidebarMenu, true);
@ -171,95 +173,6 @@ SocialUI = {
SocialMarks.populateToolbarPalette(); 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() { showLearnMore: function() {
let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "social-api"; let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "social-api";
openUILinkIn(url, "tab"); 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 = { SocialFlyout = {
get panel() { get panel() {
return document.getElementById("social-flyout-panel"); return document.getElementById("social-flyout-panel");
@ -514,15 +489,8 @@ SocialShare = {
return this.panel.lastChild; return this.panel.lastChild;
}, },
_activationHandler: function(event) {
if (!Services.prefs.getBoolPref("social.share.activationPanelEnabled"))
return;
SocialUI._activationEventHandler(event, { bypassContentCheck: true, bypassInstallPanel: true });
},
uninit: function () { uninit: function () {
if (this.iframe) { if (this.iframe) {
this.iframe.removeEventListener("ActivateSocialFeature", this._activationHandler, true, true);
this.iframe.remove(); this.iframe.remove();
} }
}, },
@ -541,7 +509,10 @@ SocialShare = {
iframe.setAttribute("disableglobalhistory", "true"); iframe.setAttribute("disableglobalhistory", "true");
iframe.setAttribute("flex", "1"); iframe.setAttribute("flex", "1");
panel.appendChild(iframe); 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(); this.populateProviderMenu();
}, },

Просмотреть файл

@ -3972,7 +3972,7 @@ var XULBrowserWindow = {
.chromeEventHandler; .chromeEventHandler;
// Ignore loads that aren't in the main tabbrowser // 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; return true;
if (!E10SUtils.shouldLoadURI(aDocShell, aURI, aReferrer)) { if (!E10SUtils.shouldLoadURI(aDocShell, aURI, aReferrer)) {

Просмотреть файл

@ -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) => { addMessageListener("ContextMenu:SaveVideoFrameAsImage", (message) => {
let video = message.objects.target; let video = message.objects.target;
let canvas = content.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); let canvas = content.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");

Просмотреть файл

@ -27,34 +27,29 @@ support-files =
unchecked.jpg unchecked.jpg
[browser_aboutHome_activation.js] [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] [browser_addons.js]
skip-if = e10s # Bug 915547 (social providers don't install)
[browser_blocklist.js] [browser_blocklist.js]
skip-if = e10s # Bug 915547 (social providers don't install)
[browser_share.js] [browser_share.js]
skip-if = e10s # Bug 915547 (social providers don't install) skip-if = e10s # Bug 1053973 (OpenGraphBuilder)
[browser_social_activation.js] [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] [browser_social_chatwindow.js]
skip-if = e10s # Bug 915547 (social providers don't install)
[browser_social_chatwindow_resize.js] [browser_social_chatwindow_resize.js]
skip-if = e10s # Bug 915547 (social providers don't install)
[browser_social_chatwindowfocus.js] [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_errorPage.js]
[browser_social_flyout.js] [browser_social_flyout.js]
skip-if = e10s # when we backed out bug 1047603, this test broke. skip-if = e10s # when we backed out bug 1047603, this test broke.
[browser_social_isVisible.js] [browser_social_isVisible.js]
[browser_social_marks.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] [browser_social_multiprovider.js]
skip-if = e10s # Bug 1069162 - lots of orange skip-if = e10s # Bug 1069162 - lots of orange
[browser_social_multiworker.js] [browser_social_multiworker.js]
[browser_social_perwindowPB.js] [browser_social_perwindowPB.js]
[browser_social_sidebar.js] [browser_social_sidebar.js]
[browser_social_status.js] [browser_social_status.js]
skip-if = e10s # Bug 915547 (social providers don't install)
[browser_social_window.js] [browser_social_window.js]
[browser_social_workercrash.js] [browser_social_workercrash.js]
#skip-if = !crashreporter #skip-if = !crashreporter

Просмотреть файл

@ -193,7 +193,13 @@ var tests = {
let installFrom = doc.nodePrincipal.origin; let installFrom = doc.nodePrincipal.origin;
Services.prefs.setCharPref("social.whitelist", ""); Services.prefs.setCharPref("social.whitelist", "");
is(SocialService.getOriginActivationType(installFrom), "foreign", "testing foriegn install"); 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"); Services.prefs.clearUserPref("social.whitelist");
SocialService.enableProvider(addonManifest.origin, function(provider) { SocialService.enableProvider(addonManifest.origin, function(provider) {
Social.uninstallProvider(addonManifest.origin); Social.uninstallProvider(addonManifest.origin);
@ -217,7 +223,13 @@ var tests = {
let installFrom = doc.nodePrincipal.origin; let installFrom = doc.nodePrincipal.origin;
Services.prefs.setCharPref("social.directories", installFrom); Services.prefs.setCharPref("social.directories", installFrom);
is(SocialService.getOriginActivationType(installFrom), "directory", "testing directory install"); 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"); Services.prefs.clearUserPref("social.directories");
SocialService.enableProvider(addonManifest.origin, function(provider) { SocialService.enableProvider(addonManifest.origin, function(provider) {
Social.uninstallProvider(addonManifest.origin); Social.uninstallProvider(addonManifest.origin);
@ -241,7 +253,13 @@ var tests = {
let doc = tab.linkedBrowser.contentDocument; let doc = tab.linkedBrowser.contentDocument;
let installFrom = doc.nodePrincipal.origin; let installFrom = doc.nodePrincipal.origin;
Services.prefs.setCharPref("social.whitelist", installFrom); 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) { SocialService.enableProvider(addonManifest.origin, function(provider) {
is(provider.manifest.version, 1, "manifest version is 1"); is(provider.manifest.version, 1, "manifest version is 1");

Просмотреть файл

@ -113,7 +113,13 @@ var tests = {
try { try {
// expecting an exception when attempting to install a hard blocked // expecting an exception when attempting to install a hard blocked
// provider // 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); gBrowser.removeTab(tab);
finishTest(false); finishTest(false);
}); });

Просмотреть файл

@ -86,9 +86,6 @@ function activateIFrameProvider(domain, callback) {
} }
function waitForProviderLoad(cb) { 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() { waitForCondition(function() {
let sbrowser = document.getElementById("social-sidebar-browser"); let sbrowser = document.getElementById("social-sidebar-browser");
let provider = SocialSidebar.provider; let provider = SocialSidebar.provider;
@ -104,7 +101,6 @@ function waitForProviderLoad(cb) {
executeSoon(cb); executeSoon(cb);
}, },
"waitForProviderLoad: provider profile was not set"); "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"); let panel = document.getElementById("servicesInstall-notification");
PopupNotifications.panel.addEventListener("popupshown", function onpopupshown() { PopupNotifications.panel.addEventListener("popupshown", function onpopupshown() {
PopupNotifications.panel.removeEventListener("popupshown", onpopupshown); PopupNotifications.panel.removeEventListener("popupshown", onpopupshown);
info("servicesInstall-notification panel opened"); ok(!panel.hidden, "servicesInstall-notification panel opened");
if (finishActivation) if (finishActivation)
panel.button.click(); panel.button.click();
else else
panel.closebutton.click(); panel.closebutton.click();
}); });
PopupNotifications.panel.addEventListener("popuphidden", function _hidden() {
activateProvider(manifest.origin, function() { PopupNotifications.panel.removeEventListener("popuphidden", _hidden);
ok(panel.hidden, "servicesInstall-notification panel hidden");
if (!finishActivation) { if (!finishActivation) {
ok(panel.hidden, "activation panel is not showing"); ok(panel.hidden, "activation panel is not showing");
executeSoon(aCallback); 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"]; let gTestDomains = ["https://example.com", "https://test1.example.com", "https://test2.example.com"];

Просмотреть файл

@ -105,7 +105,14 @@ var tests = {
let activationURL = manifest3.origin + "/browser/browser/base/content/test/social/social_activate.html" let activationURL = manifest3.origin + "/browser/browser/base/content/test/social/social_activate.html"
addTab(activationURL, function(tab) { addTab(activationURL, function(tab) {
let doc = tab.linkedBrowser.contentDocument; 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 // enable the provider so we know the button would have appeared
SocialService.enableProvider(manifest3.origin, function(provider) { SocialService.enableProvider(manifest3.origin, function(provider) {
is(provider.origin, manifest3.origin, "provider is installed"); 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" let activationURL = manifest2.origin + "/browser/browser/base/content/test/social/social_activate.html"
addTab(activationURL, function(tab) { addTab(activationURL, function(tab) {
let doc = tab.linkedBrowser.contentDocument; 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) { SocialService.enableProvider(manifest2.origin, function(provider) {
is(provider.origin, manifest2.origin, "provider is installed"); is(provider.origin, manifest2.origin, "provider is installed");
let id = SocialMarks._toolbarHelper.idFromOrigin(manifest2.origin); let id = SocialMarks._toolbarHelper.idFromOrigin(manifest2.origin);
@ -379,7 +393,14 @@ var tests = {
let toolbar = document.getElementById("nav-bar"); let toolbar = document.getElementById("nav-bar");
addTab(activationURL, function(tab) { addTab(activationURL, function(tab) {
let doc = tab.linkedBrowser.contentDocument; 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 // enable the provider so we know the button would have appeared
SocialService.enableProvider(manifest.origin, function(provider) { SocialService.enableProvider(manifest.origin, function(provider) {
waitForCondition(function() { return CustomizableUI.getWidget(id) }, waitForCondition(function() { return CustomizableUI.getWidget(id) },

Просмотреть файл

@ -66,7 +66,13 @@ var tests = {
let activationURL = manifest3.origin + "/browser/browser/base/content/test/social/social_activate.html" let activationURL = manifest3.origin + "/browser/browser/base/content/test/social/social_activate.html"
addTab(activationURL, function(tab) { addTab(activationURL, function(tab) {
let doc = tab.linkedBrowser.contentDocument; 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 // enable the provider so we know the button would have appeared
SocialService.enableProvider(manifest3.origin, function(provider) { SocialService.enableProvider(manifest3.origin, function(provider) {
is(provider.origin, manifest3.origin, "provider is installed"); 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" let activationURL = manifest2.origin + "/browser/browser/base/content/test/social/social_activate.html"
addTab(activationURL, function(tab) { addTab(activationURL, function(tab) {
let doc = tab.linkedBrowser.contentDocument; 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) { SocialService.enableProvider(manifest2.origin, function(provider) {
is(provider.origin, manifest2.origin, "provider is installed"); is(provider.origin, manifest2.origin, "provider is installed");
let id = SocialStatus._toolbarHelper.idFromOrigin(manifest2.origin); let id = SocialStatus._toolbarHelper.idFromOrigin(manifest2.origin);

Просмотреть файл

@ -31,16 +31,11 @@ function activate(node) {
node.dispatchEvent(event); node.dispatchEvent(event);
} }
function oldActivate(node) {
var event = new CustomEvent("ActivateSocialFeature");
document.dispatchEvent(event);
}
</script> </script>
<body> <body>
nothing to see here nothing to see here
<button id="activation-old" onclick="oldActivate(this)">Activate The Demo Provider</button>
<button id="activation" onclick="activate(this)">Activate The Demo Provider</button> <button id="activation" onclick="activate(this)">Activate The Demo Provider</button>
</body> </body>

Просмотреть файл

@ -169,8 +169,8 @@ this.Social = {
return SocialService.getManifestByOrigin(origin); return SocialService.getManifestByOrigin(origin);
}, },
installProvider: function(doc, data, installCallback, aBypassUserEnable=false) { installProvider: function(data, installCallback, options={}) {
SocialService.installProvider(doc, data, installCallback, aBypassUserEnable); SocialService.installProvider(data, installCallback, options);
}, },
uninstallProvider: function(origin, aCallback) { uninstallProvider: function(origin, aCallback) {

Просмотреть файл

@ -500,7 +500,7 @@ this.SocialService = {
} }
}, },
_manifestFromData: function(type, data, principal) { _manifestFromData: function(type, data, installOrigin) {
let featureURLs = ['workerURL', 'sidebarURL', 'shareURL', 'statusURL', 'markURL']; let featureURLs = ['workerURL', 'sidebarURL', 'shareURL', 'statusURL', 'markURL'];
let resolveURLs = featureURLs.concat(['postActivationURL']); let resolveURLs = featureURLs.concat(['postActivationURL']);
@ -510,10 +510,11 @@ this.SocialService = {
Cu.reportError("SocialService.manifestFromData directory service provided manifest without origin."); Cu.reportError("SocialService.manifestFromData directory service provided manifest without origin.");
return null; return null;
} }
let URI = Services.io.newURI(data.origin, null, null); installOrigin = data.origin;
principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(URI);
} }
// force/fixup origin // force/fixup origin
let URI = Services.io.newURI(installOrigin, null, null);
principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(URI);
data.origin = principal.origin; data.origin = principal.origin;
// iconURL and name are required // iconURL and name are required
@ -544,26 +545,13 @@ this.SocialService = {
return data; return data;
}, },
_getChromeWindow: function(aWindow) { _showInstallNotification: function(data, aAddonInstaller) {
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) {
let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties"); let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.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 productName = brandBundle.GetStringFromName("brandShortName");
let message = browserBundle.formatStringFromName("service.install.description", let message = browserBundle.formatStringFromName("service.install.description",
@ -582,37 +570,34 @@ this.SocialService = {
}; };
let anchor = "servicesInstall-notification-icon"; let anchor = "servicesInstall-notification-icon";
let notificationid = "servicesInstall"; let notificationid = "servicesInstall";
chromeWin.PopupNotifications.show(browser, notificationid, message, anchor, data.window.PopupNotifications.show(data.window.gBrowser.selectedBrowser,
action, [], options); notificationid, message, anchor,
action, [], options);
}, },
installProvider: function(aDOMDocument, data, installCallback, options={}) { installProvider: function(data, installCallback, options={}) {
let manifest; data.installType = getOriginActivationType(data.origin);
let installOrigin = aDOMDocument.nodePrincipal.origin;
let installType = getOriginActivationType(installOrigin);
// if we get data, we MUST have a valid manifest generated from the data // 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) 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); let addon = new AddonWrapper(manifest);
if (addon && addon.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED) if (addon && addon.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED)
throw new Error("installProvider: provider with origin [" + throw new Error("installProvider: provider with origin [" +
installOrigin + "] is blocklisted"); data.origin + "] is blocklisted");
// manifestFromData call above will enforce correct origin. To support // manifestFromData call above will enforce correct origin. To support
// activation from about: uris, we need to be sure to use the updated // activation from about: uris, we need to be sure to use the updated
// origin on the manifest. // origin on the manifest.
installOrigin = manifest.origin; data.manifest = manifest;
let id = getAddonIDFromOrigin(manifest.origin);
let id = getAddonIDFromOrigin(installOrigin);
AddonManager.getAddonByID(id, function(aAddon) { AddonManager.getAddonByID(id, function(aAddon) {
if (aAddon && aAddon.userDisabled) { if (aAddon && aAddon.userDisabled) {
aAddon.cancelUninstall(); aAddon.cancelUninstall();
aAddon.userDisabled = false; aAddon.userDisabled = false;
} }
schedule(function () { schedule(function () {
this._installProvider(aDOMDocument, manifest, options, aManifest => { this._installProvider(data, options, aManifest => {
this._notifyProviderListeners("provider-installed", aManifest.origin); this._notifyProviderListeners("provider-installed", aManifest.origin);
installCallback(aManifest); installCallback(aManifest);
}); });
@ -620,21 +605,20 @@ this.SocialService = {
}.bind(this)); }.bind(this));
}, },
_installProvider: function(aDOMDocument, manifest, options, installCallback) { _installProvider: function(data, options, installCallback) {
if (!manifest) if (!data.manifest)
throw new Error("Cannot install provider without manifest data"); throw new Error("Cannot install provider without manifest data");
let installType = getOriginActivationType(aDOMDocument.nodePrincipal.origin); if (data.installType == "foreign" && !Services.prefs.getBoolPref("social.remote-install.enabled"))
if (installType == "foreign" && !Services.prefs.getBoolPref("social.remote-install.enabled"))
throw new Error("Remote install of services is disabled"); 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 || let bypassPanel = options.bypassInstallPanel ||
(installType == "internal" && manifest.oneclick); (data.installType == "internal" && data.manifest.oneclick);
if (bypassPanel) if (bypassPanel)
installer.install(); installer.install();
else else
this._showInstallNotification(aDOMDocument, installer); this._showInstallNotification(data, installer);
}, },
createWrapper: function(manifest) { createWrapper: function(manifest) {
@ -647,11 +631,9 @@ this.SocialService = {
* the front end to deal with any reload. * the front end to deal with any reload.
*/ */
updateProvider: function(aUpdateOrigin, aManifest) { updateProvider: function(aUpdateOrigin, aManifest) {
let originUri = Services.io.newURI(aUpdateOrigin, null, null);
let principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(originUri);
let installType = this.getOriginActivationType(aUpdateOrigin); let installType = this.getOriginActivationType(aUpdateOrigin);
// if we get data, we MUST have a valid manifest generated from the data // 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) if (!manifest)
throw new Error("SocialService.installProvider: service configuration is invalid from " + aUpdateOrigin); throw new Error("SocialService.installProvider: service configuration is invalid from " + aUpdateOrigin);