mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 786133 allow install of social providers from AMO and web, r=felipe
This commit is contained in:
parent
4ba30c9fe9
commit
ceb799bb8e
File diff suppressed because one or more lines are too long
@ -111,7 +111,7 @@
|
||||
<command id="Social:SharePage" oncommand="SocialShareButton.sharePage();" disabled="true"/>
|
||||
<command id="Social:UnsharePage" oncommand="SocialShareButton.unsharePage();"/>
|
||||
<command id="Social:ToggleSidebar" oncommand="Social.toggleSidebar();"/>
|
||||
<command id="Social:ToggleNotifications" oncommand="Social.toggleNotifications();"/>
|
||||
<command id="Social:ToggleNotifications" oncommand="Social.toggleNotifications();" hidden="true"/>
|
||||
<command id="Social:FocusChat" oncommand="SocialChatBar.focus();" hidden="true" disabled="true"/>
|
||||
<command id="Social:Toggle" oncommand="Social.toggle();" hidden="true"/>
|
||||
<command id="Social:Addons" oncommand="BrowserOpenAddonsMgr('addons://list/service');"/>
|
||||
|
@ -202,19 +202,21 @@ let SocialUI = {
|
||||
// This handles "ActivateSocialFeature" events fired against content documents
|
||||
// in this window.
|
||||
_activationEventHandler: function SocialUI_activationHandler(e) {
|
||||
let targetDoc = e.target;
|
||||
|
||||
// Event must be fired against the document
|
||||
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;
|
||||
|
||||
// Ignore events fired in background tabs
|
||||
if (targetDoc.defaultView.top != content)
|
||||
return;
|
||||
|
||||
// Check that the associated document's origin is in our whitelist
|
||||
let providerOrigin = targetDoc.nodePrincipal.origin;
|
||||
if (!Social.canActivateOrigin(providerOrigin))
|
||||
// Ignore events fired in background tabs or iframes
|
||||
if (targetDoc.defaultView != content)
|
||||
return;
|
||||
|
||||
// If we are in PB mode, we silently do nothing (bug 829404 exists to
|
||||
@ -228,11 +230,34 @@ let SocialUI = {
|
||||
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.location.href, data, function(manifest) {
|
||||
this.doActivation(manifest.origin);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
doActivation: function SocialUI_doActivation(origin) {
|
||||
// Keep track of the old provider in case of undo
|
||||
let oldOrigin = Social.provider ? Social.provider.origin : "";
|
||||
|
||||
// Enable the social functionality, and indicate that it was activated
|
||||
Social.activateFromOrigin(providerOrigin, function(provider) {
|
||||
Social.activateFromOrigin(origin, function(provider) {
|
||||
// Provider to activate may not have been found
|
||||
if (!provider)
|
||||
return;
|
||||
@ -271,6 +296,7 @@ let SocialUI = {
|
||||
let oldOrigin = this.notificationPanel.getAttribute("oldorigin");
|
||||
Social.deactivateFromOrigin(origin, oldOrigin);
|
||||
this.notificationPanel.hidePopup();
|
||||
Social.uninstallProvider(origin);
|
||||
},
|
||||
|
||||
get notificationPanel() {
|
||||
@ -365,7 +391,7 @@ let SocialChatBar = {
|
||||
let command = document.getElementById("Social:FocusChat");
|
||||
if (!this.isAvailable) {
|
||||
this.chatbar.removeAll();
|
||||
command.hidden = true;
|
||||
this.chatbar.hidden = command.hidden = true;
|
||||
} else {
|
||||
this.chatbar.hidden = command.hidden = document.mozFullScreen;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ _BROWSER_FILES = \
|
||||
blocklistEmpty.xml \
|
||||
browser_blocklist.js \
|
||||
browser_addons.js \
|
||||
browser_social_activation.js \
|
||||
browser_social_perwindowPB.js \
|
||||
browser_social_toolbar.js \
|
||||
browser_social_shareButton.js \
|
||||
@ -27,6 +28,8 @@ _BROWSER_FILES = \
|
||||
browser_social_chatwindowfocus.js \
|
||||
browser_social_multiprovider.js \
|
||||
browser_social_errorPage.js \
|
||||
social_activate.html \
|
||||
social_activate_iframe.html \
|
||||
social_panel.html \
|
||||
social_share_image.png \
|
||||
social_sidebar.html \
|
||||
|
@ -6,6 +6,7 @@ let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).So
|
||||
const ADDON_TYPE_SERVICE = "service";
|
||||
const ID_SUFFIX = "@services.mozilla.org";
|
||||
const STRING_TYPE_NAME = "type.%ID%.name";
|
||||
const XPINSTALL_URL = "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul";
|
||||
|
||||
let manifest = { // normal provider
|
||||
name: "provider 1",
|
||||
@ -14,17 +15,55 @@ let manifest = { // normal provider
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
|
||||
};
|
||||
let manifest2 = { // used for testing install
|
||||
name: "provider 2",
|
||||
origin: "https://example1.com",
|
||||
sidebarURL: "https://example1.com/browser/browser/base/content/test/social/social_sidebar.html",
|
||||
workerURL: "https://example1.com/browser/browser/base/content/test/social/social_worker.js",
|
||||
iconURL: "https://example1.com/browser/browser/base/content/test/moz.png"
|
||||
};
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
Services.prefs.setCharPref("social.manifest.good", JSON.stringify(manifest));
|
||||
Services.prefs.setBoolPref("social.remote-install.enabled", true);
|
||||
runSocialTests(tests, undefined, undefined, function () {
|
||||
Services.prefs.clearUserPref("social.remote-install.enabled");
|
||||
Services.prefs.clearUserPref("social.manifest.good");
|
||||
// just in case the tests failed, clear these here as well
|
||||
Services.prefs.clearUserPref("social.whitelist");
|
||||
Services.prefs.clearUserPref("social.directories");
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
function installListener(next) {
|
||||
let expectEvent = "onInstalling";
|
||||
return {
|
||||
onInstalling: function(addon) {
|
||||
is(expectEvent, "onInstalling", "install started");
|
||||
is(addon.manifest.origin, manifest2.origin, "provider about to be installed");
|
||||
expectEvent = "onInstalled";
|
||||
},
|
||||
onInstalled: function(addon) {
|
||||
is(addon.manifest.origin, manifest2.origin, "provider installed");
|
||||
expectEvent = "onUninstalling";
|
||||
},
|
||||
onUninstalling: function(addon) {
|
||||
is(expectEvent, "onUninstalling", "uninstall started");
|
||||
is(addon.manifest.origin, manifest2.origin, "provider about to be uninstalled");
|
||||
expectEvent = "onUninstalled";
|
||||
},
|
||||
onUninstalled: function(addon) {
|
||||
is(expectEvent, "onUninstalled", "provider has been uninstalled");
|
||||
is(addon.manifest.origin, manifest2.origin, "provider uninstalled");
|
||||
AddonManager.removeAddonListener(this);
|
||||
next();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var tests = {
|
||||
testInstalledProviders: function(next) {
|
||||
// tests that our builtin manfests are actually available to the addon
|
||||
@ -129,5 +168,69 @@ var tests = {
|
||||
next();
|
||||
});
|
||||
});
|
||||
},
|
||||
testForeignInstall: function(next) {
|
||||
AddonManager.addAddonListener(installListener(next));
|
||||
|
||||
// we expect the addon install dialog to appear, we need to accept the
|
||||
// install from the dialog.
|
||||
let windowListener = {
|
||||
onWindowTitleChange: function() {},
|
||||
onCloseWindow: function() {},
|
||||
onOpenWindow: function(window) {
|
||||
var domwindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindow);
|
||||
var self = this;
|
||||
waitForFocus(function() {
|
||||
self.windowReady(domwindow);
|
||||
}, domwindow);
|
||||
},
|
||||
windowReady: function(window) {
|
||||
if (window.document.location.href == XPINSTALL_URL) {
|
||||
// Initially the accept button is disabled on a countdown timer
|
||||
var button = window.document.documentElement.getButton("accept");
|
||||
button.disabled = false;
|
||||
window.document.documentElement.acceptDialog();
|
||||
Services.wm.removeListener(windowListener);
|
||||
}
|
||||
}
|
||||
};
|
||||
Services.wm.addListener(windowListener);
|
||||
|
||||
let installFrom = "https://example1.com";
|
||||
Services.prefs.setCharPref("social.whitelist", "");
|
||||
is(SocialService.getOriginActivationType(installFrom), "foreign", "testing foriegn install");
|
||||
Social.installProvider(installFrom, manifest2, function(addonManifest) {
|
||||
Services.prefs.clearUserPref("social.whitelist");
|
||||
SocialService.addBuiltinProvider(addonManifest.origin, function(provider) {
|
||||
Social.uninstallProvider(addonManifest.origin);
|
||||
});
|
||||
});
|
||||
},
|
||||
testWhitelistInstall: function(next) {
|
||||
AddonManager.addAddonListener(installListener(next));
|
||||
|
||||
let installFrom = "https://example1.com";
|
||||
Services.prefs.setCharPref("social.whitelist", installFrom);
|
||||
is(SocialService.getOriginActivationType(installFrom), "whitelist", "testing whitelist install");
|
||||
Social.installProvider(installFrom, manifest2, function(addonManifest) {
|
||||
Services.prefs.clearUserPref("social.whitelist");
|
||||
SocialService.addBuiltinProvider(addonManifest.origin, function(provider) {
|
||||
Social.uninstallProvider(addonManifest.origin);
|
||||
});
|
||||
});
|
||||
},
|
||||
testDirectoryInstall: function(next) {
|
||||
AddonManager.addAddonListener(installListener(next));
|
||||
|
||||
let installFrom = "https://addons.allizom.org";
|
||||
Services.prefs.setCharPref("social.directories", installFrom);
|
||||
is(SocialService.getOriginActivationType(installFrom), "directory", "testing directory install");
|
||||
Social.installProvider(installFrom, manifest2, function(addonManifest) {
|
||||
Services.prefs.clearUserPref("social.directories");
|
||||
SocialService.addBuiltinProvider(addonManifest.origin, function(provider) {
|
||||
Social.uninstallProvider(addonManifest.origin);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -96,6 +96,28 @@ var tests = {
|
||||
}
|
||||
});
|
||||
},
|
||||
testInstallingBlockedProvider: function(next) {
|
||||
function finish(good) {
|
||||
ok(good, "Unable to add blocklisted provider");
|
||||
Services.prefs.clearUserPref("social.whitelist");
|
||||
setAndUpdateBlocklist(blocklistEmpty, next);
|
||||
}
|
||||
let installFrom = "https://bad.com";
|
||||
// whitelist to avoid the 3rd party install dialog, we only want to test
|
||||
// the blocklist inside installProvider.
|
||||
Services.prefs.setCharPref("social.whitelist", installFrom);
|
||||
setAndUpdateBlocklist(blocklistURL, function() {
|
||||
try {
|
||||
// expecting an exception when attempting to install a hard blocked
|
||||
// provider
|
||||
Social.installProvider(installFrom, manifest_bad, function(addonManifest) {
|
||||
finish(false);
|
||||
});
|
||||
} catch(e) {
|
||||
finish(true);
|
||||
}
|
||||
});
|
||||
},
|
||||
testBlockingExistingProvider: function(next) {
|
||||
|
||||
addWindowListener(URI_EXTENSION_BLOCKLIST_DIALOG, function(win) {
|
||||
|
217
browser/base/content/test/social/browser_social_activation.js
Normal file
217
browser/base/content/test/social/browser_social_activation.js
Normal file
@ -0,0 +1,217 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
|
||||
|
||||
let tabsToRemove = [];
|
||||
|
||||
function postTestCleanup(callback) {
|
||||
Social.provider = null;
|
||||
// any tabs opened by the test.
|
||||
for (let tab of tabsToRemove)
|
||||
gBrowser.removeTab(tab);
|
||||
tabsToRemove = [];
|
||||
// theses tests use the notification panel but don't bother waiting for it
|
||||
// to fully open - the end result is that the panel might stay open
|
||||
SocialUI.notificationPanel.hidePopup();
|
||||
|
||||
Services.prefs.clearUserPref("social.whitelist");
|
||||
|
||||
// all providers may have had their manifests added.
|
||||
for (let manifest of gProviders)
|
||||
Services.prefs.clearUserPref("social.manifest." + manifest.origin);
|
||||
// all the providers may have been added.
|
||||
let numRemoved = 0;
|
||||
let cbRemoved = function() {
|
||||
if (++numRemoved == gProviders.length) {
|
||||
executeSoon(function() {
|
||||
is(Social.providers.length, 0, "all providers removed");
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
for (let [i, manifest] of Iterator(gProviders)) {
|
||||
try {
|
||||
SocialService.removeProvider(manifest.origin, cbRemoved);
|
||||
} catch(ex) {
|
||||
// this test didn't add this provider - that's ok.
|
||||
cbRemoved();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addBuiltinManifest(manifest) {
|
||||
Services.prefs.setCharPref("social.manifest." + manifest.origin, JSON.stringify(manifest));
|
||||
}
|
||||
|
||||
function addTab(url, callback) {
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab(url, {skipAnimation: true});
|
||||
tab.linkedBrowser.addEventListener("load", function tabLoad(event) {
|
||||
tab.linkedBrowser.removeEventListener("load", tabLoad, true);
|
||||
tabsToRemove.push(tab);
|
||||
executeSoon(function() {callback(tab)});
|
||||
}, true);
|
||||
}
|
||||
|
||||
function sendActivationEvent(tab, callback) {
|
||||
// hack Social.lastEventReceived so we don't hit the "too many events" check.
|
||||
Social.lastEventReceived = 0;
|
||||
let doc = tab.linkedBrowser.contentDocument;
|
||||
// if our test has a frame, use it
|
||||
if (doc.defaultView.frames[0])
|
||||
doc = doc.defaultView.frames[0].document;
|
||||
let button = doc.getElementById("activation");
|
||||
EventUtils.synthesizeMouseAtCenter(button, {}, doc.defaultView);
|
||||
executeSoon(callback);
|
||||
}
|
||||
|
||||
function activateProvider(domain, callback) {
|
||||
let activationURL = domain+"/browser/browser/base/content/test/social/social_activate.html"
|
||||
addTab(activationURL, function(tab) {
|
||||
sendActivationEvent(tab, callback);
|
||||
});
|
||||
}
|
||||
|
||||
function activateIFrameProvider(domain, callback) {
|
||||
let activationURL = domain+"/browser/browser/base/content/test/social/social_activate_iframe.html"
|
||||
addTab(activationURL, function(tab) {
|
||||
sendActivationEvent(tab, callback);
|
||||
});
|
||||
}
|
||||
|
||||
let gTestDomains = ["https://example.com", "https://test1.example.com", "https://test2.example.com"];
|
||||
let gProviders = [
|
||||
{
|
||||
name: "provider 1",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html?provider1",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js#no-profile,no-recommend",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
},
|
||||
{
|
||||
name: "provider 2",
|
||||
origin: "https://test1.example.com",
|
||||
sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar.html?provider2",
|
||||
workerURL: "https://test1.example.com/browser/browser/base/content/test/social/social_worker.js#no-profile,no-recommend",
|
||||
iconURL: "chrome://branding/content/icon64.png"
|
||||
},
|
||||
{
|
||||
name: "provider 3",
|
||||
origin: "https://test2.example.com",
|
||||
sidebarURL: "https://test2.example.com/browser/browser/base/content/test/social/social_sidebar.html?provider2",
|
||||
workerURL: "https://test2.example.com/browser/browser/base/content/test/social/social_worker.js#no-profile,no-recommend",
|
||||
iconURL: "chrome://branding/content/about-logo.png"
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
runSocialTests(tests, undefined, postTestCleanup);
|
||||
}
|
||||
|
||||
var tests = {
|
||||
testActivationWrongOrigin: function(next) {
|
||||
// At this stage none of our providers exist, so we expect failure.
|
||||
Services.prefs.setBoolPref("social.remote-install.enabled", false);
|
||||
activateProvider(gTestDomains[0], function() {
|
||||
is(SocialUI.enabled, false, "SocialUI is not enabled");
|
||||
ok(SocialUI.notificationPanel.hidden, "activation panel still hidden");
|
||||
checkSocialUI();
|
||||
Services.prefs.clearUserPref("social.remote-install.enabled");
|
||||
next();
|
||||
});
|
||||
},
|
||||
|
||||
testIFrameActivation: function(next) {
|
||||
Services.prefs.setCharPref("social.whitelist", gTestDomains.join(","));
|
||||
activateIFrameProvider(gTestDomains[0], function() {
|
||||
is(SocialUI.enabled, false, "SocialUI is not enabled");
|
||||
ok(!Social.provider, "provider is not installed");
|
||||
ok(SocialUI.notificationPanel.hidden, "activation panel still hidden");
|
||||
checkSocialUI();
|
||||
Services.prefs.clearUserPref("social.whitelist");
|
||||
next();
|
||||
});
|
||||
},
|
||||
|
||||
testActivationFirstProvider: function(next) {
|
||||
Services.prefs.setCharPref("social.whitelist", gTestDomains.join(","));
|
||||
// first up we add a manifest entry for a single provider.
|
||||
activateProvider(gTestDomains[0], function() {
|
||||
ok(!SocialUI.notificationPanel.hidden, "activation panel should be showing");
|
||||
is(Social.provider.origin, gTestDomains[0], "new provider is active");
|
||||
checkSocialUI();
|
||||
// hit "undo"
|
||||
document.getElementById("social-undoactivation-button").click();
|
||||
executeSoon(function() {
|
||||
// we deactivated leaving no providers left, so Social is disabled.
|
||||
ok(!Social.provider, "should be no provider left after disabling");
|
||||
checkSocialUI();
|
||||
Services.prefs.clearUserPref("social.whitelist");
|
||||
next();
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
testActivationMultipleProvider: function(next) {
|
||||
// The trick with this test is to make sure that Social.providers[1] is
|
||||
// the current provider when doing the undo - this makes sure that the
|
||||
// Social code doesn't fallback to Social.providers[0], which it will
|
||||
// do in some cases (but those cases do not include what this test does)
|
||||
// first enable the 2 providers
|
||||
Services.prefs.setCharPref("social.whitelist", gTestDomains.join(","));
|
||||
SocialService.addProvider(gProviders[0], function() {
|
||||
SocialService.addProvider(gProviders[1], function() {
|
||||
Social.provider = Social.providers[1];
|
||||
checkSocialUI();
|
||||
// activate the last provider.
|
||||
addBuiltinManifest(gProviders[2]);
|
||||
activateProvider(gTestDomains[2], function() {
|
||||
ok(!SocialUI.notificationPanel.hidden, "activation panel should be showing");
|
||||
is(Social.provider.origin, gTestDomains[2], "new provider is active");
|
||||
checkSocialUI();
|
||||
// hit "undo"
|
||||
document.getElementById("social-undoactivation-button").click();
|
||||
executeSoon(function() {
|
||||
// we deactivated - the first provider should be enabled.
|
||||
is(Social.provider.origin, Social.providers[1].origin, "original provider should have been reactivated");
|
||||
checkSocialUI();
|
||||
Services.prefs.clearUserPref("social.whitelist");
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
testRemoveNonCurrentProvider: function(next) {
|
||||
Services.prefs.setCharPref("social.whitelist", gTestDomains.join(","));
|
||||
SocialService.addProvider(gProviders[0], function() {
|
||||
SocialService.addProvider(gProviders[1], function() {
|
||||
Social.provider = Social.providers[1];
|
||||
checkSocialUI();
|
||||
// activate the last provider.
|
||||
addBuiltinManifest(gProviders[2]);
|
||||
activateProvider(gTestDomains[2], function() {
|
||||
ok(!SocialUI.notificationPanel.hidden, "activation panel should be showing");
|
||||
is(Social.provider.origin, gTestDomains[2], "new provider is active");
|
||||
checkSocialUI();
|
||||
// A bit contrived, but set a new provider current while the
|
||||
// activation ui is up.
|
||||
Social.provider = Social.providers[1];
|
||||
// hit "undo"
|
||||
document.getElementById("social-undoactivation-button").click();
|
||||
executeSoon(function() {
|
||||
// we deactivated - the same provider should be enabled.
|
||||
is(Social.provider.origin, Social.providers[1].origin, "original provider still be active");
|
||||
checkSocialUI();
|
||||
Services.prefs.clearUserPref("social.whitelist");
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
}
|
@ -81,7 +81,7 @@ function runSocialTestWithProvider(manifest, callback) {
|
||||
SocialService.removeProvider(origin, cb);
|
||||
} catch (ex) {
|
||||
// Ignore "provider doesn't exist" errors.
|
||||
if (ex.message == "SocialService.removeProvider: no provider with this origin exists!")
|
||||
if (ex.message.indexOf("SocialService.removeProvider: no provider with origin") == 0)
|
||||
return;
|
||||
info("Failed to clean up provider " + origin + ": " + ex);
|
||||
}
|
||||
@ -181,7 +181,7 @@ function checkSocialUI(win) {
|
||||
isbool(win.SocialSidebar.opened, enabled, "social sidebar open?");
|
||||
isbool(win.SocialChatBar.isAvailable, enabled && Social.haveLoggedInUser(), "chatbar available?");
|
||||
isbool(!win.SocialChatBar.chatbar.hidden, enabled && Social.haveLoggedInUser(), "chatbar visible?");
|
||||
isbool(!win.SocialShareButton.shareButton.hidden, enabled && provider.recommendInfo, "share button visible?");
|
||||
isbool(!win.SocialShareButton.shareButton.hidden, enabled && Social.haveLoggedInUser() && provider.recommendInfo, "share button visible?");
|
||||
isbool(!doc.getElementById("social-toolbar-item").hidden, enabled, "toolbar items visible?");
|
||||
if (enabled)
|
||||
is(win.SocialToolbar.button.style.listStyleImage, 'url("' + provider.iconURL + '")', "toolbar button has provider icon");
|
||||
@ -191,7 +191,7 @@ function checkSocialUI(win) {
|
||||
isbool(!doc.getElementById("Social:ToggleNotifications").hidden, enabled, "Social:ToggleNotifications visible?");
|
||||
isbool(!doc.getElementById("Social:FocusChat").hidden, enabled && Social.haveLoggedInUser(), "Social:FocusChat visible?");
|
||||
isbool(doc.getElementById("Social:FocusChat").getAttribute("disabled"), enabled ? "false" : "true", "Social:FocusChat disabled?");
|
||||
is(doc.getElementById("Social:SharePage").getAttribute("disabled"), enabled && provider.recommendInfo ? "false" : "true", "Social:SharePage visible?");
|
||||
is(doc.getElementById("Social:SharePage").getAttribute("disabled"), enabled && Social.haveLoggedInUser() && provider.recommendInfo ? "false" : "true", "Social:SharePage visible?");
|
||||
|
||||
// broadcasters.
|
||||
isbool(!doc.getElementById("socialActiveBroadcaster").hidden, enabled, "socialActiveBroadcaster hidden?");
|
||||
|
39
browser/base/content/test/social/social_activate.html
Normal file
39
browser/base/content/test/social/social_activate.html
Normal file
@ -0,0 +1,39 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Activation test</title>
|
||||
</head>
|
||||
<script>
|
||||
// icons from http://findicons.com/icon/158311/firefox?id=356182 by ipapun
|
||||
var data = {
|
||||
// currently required
|
||||
"name": "Demo Social Service",
|
||||
"iconURL": "chrome://branding/content/icon16.png",
|
||||
"icon32URL": "chrome://branding/content/favicon32.png",
|
||||
"icon64URL": "chrome://branding/content/icon64.png",
|
||||
|
||||
// at least one of these must be defined
|
||||
"workerURL": "/browser/browser/base/content/test/social/social_sidebar.html",
|
||||
"sidebarURL": "/browser/browser/base/content/test/social/social_worker.js",
|
||||
|
||||
// should be available for display purposes
|
||||
"description": "A short paragraph about this provider",
|
||||
"author": "Shane Caraveo, Mozilla",
|
||||
|
||||
// optional
|
||||
"version": "1.0"
|
||||
}
|
||||
|
||||
function activate(node) {
|
||||
node.setAttribute("data-service", JSON.stringify(data));
|
||||
var event = new CustomEvent("ActivateSocialFeature");
|
||||
node.dispatchEvent(event);
|
||||
}
|
||||
</script>
|
||||
<body>
|
||||
|
||||
nothing to see here
|
||||
|
||||
<button id="activation" onclick="activate(this)">Activate The Demo Provider</button>
|
||||
|
||||
</body>
|
||||
</html>
|
11
browser/base/content/test/social/social_activate_iframe.html
Normal file
11
browser/base/content/test/social/social_activate_iframe.html
Normal file
@ -0,0 +1,11 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Activation iframe test</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<iframe src="social_activate.html"/>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -173,6 +173,14 @@ this.Social = {
|
||||
return null;
|
||||
},
|
||||
|
||||
installProvider: function(origin ,sourceURI, data, installCallback) {
|
||||
SocialService.installProvider(origin ,sourceURI, data, installCallback);
|
||||
},
|
||||
|
||||
uninstallProvider: function(origin) {
|
||||
SocialService.uninstallProvider(origin);
|
||||
},
|
||||
|
||||
// Activation functionality
|
||||
activateFromOrigin: function (origin, callback) {
|
||||
// For now only "builtin" providers can be activated. It's OK if the
|
||||
@ -200,10 +208,6 @@ this.Social = {
|
||||
SocialService.removeProvider(origin);
|
||||
},
|
||||
|
||||
canActivateOrigin: function (origin) {
|
||||
return SocialService.canActivateOrigin(origin);
|
||||
},
|
||||
|
||||
// Sharing functionality
|
||||
_getShareablePageUrl: function Social_getShareablePageUrl(aURI) {
|
||||
let uri = aURI.clone();
|
||||
|
@ -20,6 +20,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "WorkerAPI", "resource://gre/modules/Wor
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "MozSocialAPI", "resource://gre/modules/MozSocialAPI.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask", "resource://gre/modules/DeferredTask.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, 'bs',
|
||||
"@mozilla.org/extensions/blocklist;1",
|
||||
"nsIBlocklistService");
|
||||
|
||||
/**
|
||||
* The SocialService is the public API to social providers - it tracks which
|
||||
* providers are installed and enabled, and is the entry-point for access to
|
||||
@ -54,6 +58,25 @@ let SocialServiceInternal = {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
getManifestPrefname: function(origin) {
|
||||
// Retrieve the prefname for a given origin/manifest.
|
||||
// If no existing pref, return a generated prefname.
|
||||
let MANIFEST_PREFS = Services.prefs.getBranch("social.manifest.");
|
||||
let prefs = MANIFEST_PREFS.getChildList("", []);
|
||||
for (let pref of prefs) {
|
||||
try {
|
||||
var manifest = JSON.parse(MANIFEST_PREFS.getCharPref(pref));
|
||||
if (manifest.origin == origin) {
|
||||
return pref;
|
||||
}
|
||||
} catch (err) {
|
||||
Cu.reportError("SocialService: failed to load manifest: " + pref +
|
||||
", exception: " + err);
|
||||
}
|
||||
}
|
||||
let originUri = Services.io.newURI(origin, null, null);
|
||||
return originUri.hostPort.replace('.','-');
|
||||
}
|
||||
};
|
||||
|
||||
@ -271,12 +294,21 @@ this.SocialService = {
|
||||
});
|
||||
},
|
||||
|
||||
canActivateOrigin: function canActivateOrigin(origin) {
|
||||
getOriginActivationType: function(origin) {
|
||||
for (let manifest in SocialServiceInternal.manifests) {
|
||||
if (manifest.origin == origin)
|
||||
return true;
|
||||
return 'builtin';
|
||||
}
|
||||
return false;
|
||||
|
||||
let whitelist = Services.prefs.getCharPref("social.whitelist").split(',');
|
||||
if (whitelist.indexOf(origin) >= 0)
|
||||
return 'whitelist';
|
||||
|
||||
let directories = Services.prefs.getCharPref("social.directories").split(',');
|
||||
if (directories.indexOf(origin) >= 0)
|
||||
return 'directory';
|
||||
|
||||
return 'foreign';
|
||||
},
|
||||
|
||||
_providerListeners: new Map(),
|
||||
@ -295,6 +327,110 @@ this.SocialService = {
|
||||
Components.utils.reportError("SocialService: provider listener threw an exception: " + ex);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_manifestFromData: function(type, data, principal) {
|
||||
let sameOriginRequired = ['workerURL', 'sidebarURL'];
|
||||
|
||||
if (type == 'directory') {
|
||||
// directory provided manifests must have origin in manifest, use that
|
||||
if (!data['origin']) {
|
||||
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);
|
||||
}
|
||||
// force/fixup origin
|
||||
data.origin = principal.origin;
|
||||
|
||||
// workerURL, sidebarURL is required and must be same-origin
|
||||
// iconURL and name are required
|
||||
// iconURL may be a different origin (CDN or data url support) if this is
|
||||
// a whitelisted or directory listed provider
|
||||
if (!data['workerURL'] || !data['sidebarURL']) {
|
||||
Cu.reportError("SocialService.manifestFromData manifest missing required workerURL or sidebarURL.");
|
||||
return null;
|
||||
}
|
||||
if (!data['name'] || !data['iconURL']) {
|
||||
Cu.reportError("SocialService.manifestFromData manifest missing name or iconURL.");
|
||||
return null;
|
||||
}
|
||||
for (let url of sameOriginRequired) {
|
||||
if (data[url]) {
|
||||
try {
|
||||
data[url] = Services.io.newURI(principal.URI.resolve(data[url]), null, null).spec;
|
||||
} catch(e) {
|
||||
Cu.reportError("SocialService.manifestFromData same-origin missmatch in manifest for " + principal.origin);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
installProvider: function(sourceURI, data, installCallback) {
|
||||
let URI = Services.io.newURI(sourceURI, null, null);
|
||||
let principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(URI);
|
||||
let installOrigin = principal.origin;
|
||||
|
||||
let id = getAddonIDFromOrigin(installOrigin);
|
||||
if (bs.getAddonBlocklistState(id, data.version || "0") == Ci.nsIBlocklistService.STATE_BLOCKED)
|
||||
throw new Error("installProvider: provider with origin [" +
|
||||
installOrigin + "] is blocklisted");
|
||||
|
||||
let installType = this.getOriginActivationType(installOrigin);
|
||||
let manifest;
|
||||
if (data) {
|
||||
// if we get data, we MUST have a valid manifest generated from the data
|
||||
manifest = this._manifestFromData(installType, data, principal);
|
||||
if (!manifest)
|
||||
throw new Error("SocialService.installProvider: service configuration is invalid from " + sourceURI);
|
||||
}
|
||||
switch(installType) {
|
||||
case "foreign":
|
||||
if (!Services.prefs.getBoolPref("social.remote-install.enabled"))
|
||||
throw new Error("Remote install of services is disabled");
|
||||
if (!manifest)
|
||||
throw new Error("Cannot install provider without manifest data");
|
||||
let args = {};
|
||||
args.url = this.url;
|
||||
args.installs = [new AddonInstaller(sourceURI, manifest, installCallback)];
|
||||
args.wrappedJSObject = args;
|
||||
|
||||
// Bug 836452, get something better than the scary addon dialog
|
||||
Services.ww.openWindow(this.window, "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul",
|
||||
null, "chrome,modal,centerscreen", args);
|
||||
break;
|
||||
case "builtin":
|
||||
// for builtin, we already have a manifest, but it can be overridden
|
||||
// we need to return the manifest in the installcallback, so fetch
|
||||
// it if we have it. If there is no manifest data for the builtin,
|
||||
// the install request MUST be from the provider, otherwise we have
|
||||
// no way to know what provider we're trying to enable. This is
|
||||
// primarily an issue for "version zero" providers that did not
|
||||
// send the manifest with the dom event for activation.
|
||||
if (!manifest)
|
||||
manifest = SocialServiceInternal.getManifestByOrigin(installOrigin);
|
||||
case "directory":
|
||||
// a manifest is requried, and will have been vetted by reviewers
|
||||
case "whitelist":
|
||||
// a manifest is required, we'll catch a missing manifest below.
|
||||
if (!manifest)
|
||||
throw new Error("Cannot install provider without manifest data");
|
||||
let installer = new AddonInstaller(sourceURI, manifest, installCallback);
|
||||
installer.install();
|
||||
break;
|
||||
default:
|
||||
throw new Error("SocialService.installProvider: Invalid install type "+installType+"\n");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
uninstallProvider: function(origin) {
|
||||
let manifest = SocialServiceInternal.getManifestByOrigin(origin);
|
||||
let addon = new AddonWrapper(manifest);
|
||||
addon.uninstall();
|
||||
}
|
||||
};
|
||||
|
||||
@ -312,8 +448,6 @@ function SocialProvider(input) {
|
||||
throw new Error("SocialProvider must be passed an origin");
|
||||
|
||||
let id = getAddonIDFromOrigin(input.origin);
|
||||
let bs = Cc["@mozilla.org/extensions/blocklist;1"].
|
||||
getService(Ci.nsIBlocklistService);
|
||||
if (bs.getAddonBlocklistState(id, input.version || "0") == Ci.nsIBlocklistService.STATE_BLOCKED)
|
||||
throw new Error("SocialProvider: provider with origin [" +
|
||||
input.origin + "] is blocklisted");
|
||||
@ -576,14 +710,32 @@ function getAddonIDFromOrigin(origin) {
|
||||
return originUri.host + ID_SUFFIX;
|
||||
}
|
||||
|
||||
function getPrefnameFromOrigin(origin) {
|
||||
return "social.manifest." + SocialServiceInternal.getManifestPrefname(origin);
|
||||
}
|
||||
|
||||
function AddonInstaller(sourceURI, aManifest, installCallback) {
|
||||
this.sourceURI = sourceURI;
|
||||
this.install = function() {
|
||||
let addon = this.addon;
|
||||
AddonManagerPrivate.callInstallListeners("onExternalInstall", null, addon, null, false);
|
||||
AddonManagerPrivate.callAddonListeners("onInstalling", addon, false);
|
||||
Services.prefs.setCharPref(getPrefnameFromOrigin(aManifest.origin), JSON.stringify(aManifest));
|
||||
AddonManagerPrivate.callAddonListeners("onInstalled", addon);
|
||||
installCallback(aManifest);
|
||||
};
|
||||
this.cancel = function() {
|
||||
Services.prefs.clearUserPref(getPrefnameFromOrigin(aManifest.origin))
|
||||
},
|
||||
this.addon = new AddonWrapper(aManifest);
|
||||
};
|
||||
|
||||
var SocialAddonProvider = {
|
||||
startup: function() {},
|
||||
|
||||
shutdown: function() {},
|
||||
|
||||
updateAddonAppDisabledStates: function() {
|
||||
let bs = Cc["@mozilla.org/extensions/blocklist;1"].
|
||||
getService(Ci.nsIBlocklistService);
|
||||
// we wont bother with "enabling" services that are released from blocklist
|
||||
for (let manifest of SocialServiceInternal.manifests) {
|
||||
try {
|
||||
@ -615,6 +767,14 @@ var SocialAddonProvider = {
|
||||
return;
|
||||
}
|
||||
aCallback([new AddonWrapper(a) for each (a in SocialServiceInternal.manifests)]);
|
||||
},
|
||||
|
||||
removeAddon: function(aAddon) {
|
||||
AddonManagerPrivate.callAddonListeners("onUninstalling", aAddon, false);
|
||||
aAddon.pendingOperations |= AddonManager.PENDING_UNINSTALL;
|
||||
Services.prefs.clearUserPref(getPrefnameFromOrigin(aAddon.manifest.origin));
|
||||
aAddon.pendingOperations -= AddonManager.PENDING_UNINSTALL;
|
||||
AddonManagerPrivate.callAddonListeners("onUninstalled", aAddon);
|
||||
}
|
||||
}
|
||||
|
||||
@ -666,14 +826,10 @@ AddonWrapper.prototype = {
|
||||
},
|
||||
|
||||
get blocklistState() {
|
||||
let bs = Cc["@mozilla.org/extensions/blocklist;1"].
|
||||
getService(Ci.nsIBlocklistService);
|
||||
return bs.getAddonBlocklistState(this.id, this.version || "0");
|
||||
},
|
||||
|
||||
get blocklistURL() {
|
||||
let bs = Cc["@mozilla.org/extensions/blocklist;1"].
|
||||
getService(Ci.nsIBlocklistService);
|
||||
return bs.getAddonBlocklistURL(this.id, this.version || "0");
|
||||
},
|
||||
|
||||
@ -698,7 +854,9 @@ AddonWrapper.prototype = {
|
||||
|
||||
get permissions() {
|
||||
let permissions = 0;
|
||||
// XXX we will not have install until BUG 786133 lands
|
||||
// any "user defined" manifest can be removed
|
||||
if (Services.prefs.prefHasUserValue(getPrefnameFromOrigin(this.manifest.origin)))
|
||||
permissions = AddonManager.PERM_CAN_UNINSTALL;
|
||||
if (!this.appDisabled) {
|
||||
if (this.userDisabled) {
|
||||
permissions |= AddonManager.PERM_CAN_ENABLE;
|
||||
@ -786,11 +944,26 @@ AddonWrapper.prototype = {
|
||||
},
|
||||
|
||||
uninstall: function() {
|
||||
// XXX we will not uninstall until BUG 786133 lands
|
||||
let prefName = getPrefnameFromOrigin(this.manifest.origin);
|
||||
if (Services.prefs.prefHasUserValue(prefName)) {
|
||||
if (ActiveProviders.has(this.manifest.origin)) {
|
||||
SocialService.removeProvider(this.manifest.origin, function() {
|
||||
SocialAddonProvider.removeAddon(this);
|
||||
}.bind(this));
|
||||
} else {
|
||||
SocialAddonProvider.removeAddon(this);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
cancelUninstall: function() {
|
||||
// XXX we will not uninstall until BUG 786133 lands
|
||||
let prefName = getPrefnameFromOrigin(this.manifest.origin);
|
||||
if (Services.prefs.prefHasUserValue(prefName))
|
||||
throw new Error(this.manifest.name + " is not marked to be uninstalled");
|
||||
// ensure we're set into prefs
|
||||
Services.prefs.setCharPref(prefName, JSON.stringify(this.manifest));
|
||||
this._pending -= AddonManager.PENDING_UNINSTALL;
|
||||
AddonManagerPrivate.callAddonListeners("onOperationCancelled", this);
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user