import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,7 @@
"use strict";
module.exports = {
"extends": [
"../../../../../testing/mochitest/browser.eslintrc.js"
]
};

View file

@ -0,0 +1,6 @@
<?xml version="1.0"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
<emItems>
<emItem blockID="s1" id="test1.example.com@services.mozilla.org"></emItem>
</emItems>
</blocklist>

View file

@ -0,0 +1,23 @@
[DEFAULT]
support-files =
blocklist.xml
head.js
opengraph/og_invalid_url.html
opengraph/opengraph.html
opengraph/shortlink_linkrel.html
opengraph/shorturl_link.html
opengraph/shorturl_linkrel.html
microformats.html
share.html
share_activate.html
social_activate.html
social_activate_basic.html
social_activate_iframe.html
social_postActivation.html
!/browser/base/content/test/plugins/blockNoPlugins.xml
[browser_aboutHome_activation.js]
[browser_addons.js]
[browser_blocklist.js]
[browser_share.js]
[browser_social_activation.js]

View file

@ -0,0 +1,229 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AboutHomeUtils",
"resource:///modules/AboutHome.jsm");
var snippet =
' <script>' +
' var manifest = {' +
' "name": "Demo Social Service",' +
' "origin": "https://example.com",' +
' "iconURL": "chrome://branding/content/icon16.png",' +
' "icon32URL": "chrome://branding/content/icon32.png",' +
' "icon64URL": "chrome://branding/content/icon64.png",' +
' "shareURL": "https://example.com/browser/browser/base/content/test/social/social_share.html",' +
' "postActivationURL": "https://example.com/browser/browser/base/content/test/social/social_postActivation.html",' +
' };' +
' function activateProvider(node) {' +
' node.setAttribute("data-service", JSON.stringify(manifest));' +
' var event = new CustomEvent("ActivateSocialFeature");' +
' node.dispatchEvent(event);' +
' }' +
' </script>' +
' <div id="activationSnippet" onclick="activateProvider(this)">' +
' <img src="chrome://branding/content/icon32.png"></img>' +
' </div>';
// enable one-click activation
var snippet2 =
' <script>' +
' var manifest = {' +
' "name": "Demo Social Service",' +
' "origin": "https://example.com",' +
' "iconURL": "chrome://branding/content/icon16.png",' +
' "icon32URL": "chrome://branding/content/icon32.png",' +
' "icon64URL": "chrome://branding/content/icon64.png",' +
' "shareURL": "https://example.com/browser/browser/base/content/test/social/social_share.html",' +
' "postActivationURL": "https://example.com/browser/browser/base/content/test/social/social_postActivation.html",' +
' "oneclick": true' +
' };' +
' function activateProvider(node) {' +
' node.setAttribute("data-service", JSON.stringify(manifest));' +
' var event = new CustomEvent("ActivateSocialFeature");' +
' node.dispatchEvent(event);' +
' }' +
' </script>' +
' <div id="activationSnippet" onclick="activateProvider(this)">' +
' <img src="chrome://branding/content/icon32.png"></img>' +
' </div>';
var gTests = [
{
desc: "Test activation with enable panel",
snippet: snippet,
panel: true
},
{
desc: "Test activation bypassing enable panel",
snippet: snippet2,
panel: false
}
];
function test()
{
waitForExplicitFinish();
requestLongerTimeout(2);
ignoreAllUncaughtExceptions();
PopupNotifications.panel.setAttribute("animate", "false");
registerCleanupFunction(function () {
PopupNotifications.panel.removeAttribute("animate");
});
Task.spawn(function* () {
for (let test of gTests) {
info(test.desc);
// Create a tab to run the test.
let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
// Add an event handler to modify the snippets map once it's ready.
let snippetsPromise = promiseSetupSnippetsMap(tab, test.snippet);
// Start loading about:home and wait for it to complete, snippets should be loaded
yield promiseTabLoadEvent(tab, "about:home", "AboutHomeLoadSnippetsCompleted");
yield snippetsPromise;
// ensure our activation snippet is indeed available
yield ContentTask.spawn(tab.linkedBrowser, {}, function*(arg) {
ok(!!content.document.getElementById("snippets"), "Found snippets element");
ok(!!content.document.getElementById("activationSnippet"), "The snippet is present.");
});
yield new Promise(resolve => {
activateProvider(tab, test.panel).then(() => {
checkSocialUI();
SocialService.uninstallProvider("https://example.com", function () {
info("provider uninstalled");
resolve();
});
});
});
// activation opened a post-activation info tab, close it.
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
yield BrowserTestUtils.removeTab(tab);
}
}).then(finish, ex => {
ok(false, "Unexpected Exception: " + ex);
finish();
});
}
/**
* Starts a load in an existing tab and waits for it to finish (via some event).
*
* @param aTab
* The tab to load into.
* @param aUrl
* The url to load.
* @param aEvent
* The load event type to wait for. Defaults to "load".
* @return {Promise} resolved when the event is handled.
*/
function promiseTabLoadEvent(aTab, aURL, aEventType="load")
{
return new Promise(resolve => {
info("Wait tab event: " + aEventType);
aTab.linkedBrowser.addEventListener(aEventType, function load(event) {
if (event.originalTarget != aTab.linkedBrowser.contentDocument ||
event.target.location.href == "about:blank") {
info("skipping spurious load event");
return;
}
aTab.linkedBrowser.removeEventListener(aEventType, load, true);
info("Tab event received: " + aEventType);
resolve();
}, true, true);
aTab.linkedBrowser.loadURI(aURL);
});
}
/**
* Cleans up snippets and ensures that by default we don't try to check for
* remote snippets since that may cause network bustage or slowness.
*
* @param aTab
* The tab containing about:home.
* @param aSetupFn
* The setup function to be run.
* @return {Promise} resolved when the snippets are ready. Gets the snippets map.
*/
function promiseSetupSnippetsMap(aTab, aSnippet)
{
info("Waiting for snippets map");
return ContentTask.spawn(aTab.linkedBrowser,
{snippetsVersion: AboutHomeUtils.snippetsVersion,
snippet: aSnippet},
function*(arg) {
return new Promise(resolve => {
addEventListener("AboutHomeLoadSnippets", function load(event) {
removeEventListener("AboutHomeLoadSnippets", load, true);
let cw = content.window.wrappedJSObject;
// The snippets should already be ready by this point. Here we're
// just obtaining a reference to the snippets map.
cw.ensureSnippetsMapThen(function (aSnippetsMap) {
aSnippetsMap = Cu.waiveXrays(aSnippetsMap);
console.log("Got snippets map: " +
"{ last-update: " + aSnippetsMap.get("snippets-last-update") +
", cached-version: " + aSnippetsMap.get("snippets-cached-version") +
" }");
// Don't try to update.
aSnippetsMap.set("snippets-last-update", Date.now());
aSnippetsMap.set("snippets-cached-version", arg.snippetsVersion);
// Clear snippets.
aSnippetsMap.delete("snippets");
aSnippetsMap.set("snippets", arg.snippet);
resolve();
});
}, true, true);
});
});
}
function sendActivationEvent(tab) {
// 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("activationSnippet");
BrowserTestUtils.synthesizeMouseAtCenter(button, {}, tab.linkedBrowser);
}
function activateProvider(tab, expectPanel, aCallback) {
return new Promise(resolve => {
if (expectPanel) {
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown").then(() => {
let panel = document.getElementById("servicesInstall-notification");
panel.button.click();
});
}
waitForProviderLoad().then(() => {
checkSocialUI();
resolve();
});
sendActivationEvent(tab);
});
}
function waitForProviderLoad(cb) {
return Promise.all([
promiseObserverNotified("social:provider-enabled"),
ensureFrameLoaded(gBrowser, "https://example.com/browser/browser/base/content/test/social/social_postActivation.html"),
]);
}

View file

@ -0,0 +1,217 @@
var AddonManager = Cu.import("resource://gre/modules/AddonManager.jsm", {}).AddonManager;
var SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
var manifest = {
name: "provider 1",
origin: "https://example.com",
shareURL: "https://example.com/browser/browser/base/content/test/social/social_share.html",
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
};
var manifest2 = { // used for testing install
name: "provider 2",
origin: "https://test1.example.com",
shareURL: "https://test1.example.com/browser/browser/base/content/test/social/social_share.html",
iconURL: "https://test1.example.com/browser/browser/base/content/test/general/moz.png",
version: "1.0"
};
var manifestUpgrade = { // used for testing install
name: "provider 3",
origin: "https://test2.example.com",
shareURL: "https://test2.example.com/browser/browser/base/content/test/social/social_share.html",
iconURL: "https://test2.example.com/browser/browser/base/content/test/general/moz.png",
version: "1.0"
};
function test() {
waitForExplicitFinish();
PopupNotifications.panel.setAttribute("animate", "false");
registerCleanupFunction(function () {
PopupNotifications.panel.removeAttribute("animate");
});
let prefname = getManifestPrefname(manifest);
// ensure that manifest2 is NOT showing as builtin
is(SocialService.getOriginActivationType(manifest.origin), "foreign", "manifest is foreign");
is(SocialService.getOriginActivationType(manifest2.origin), "foreign", "manifest2 is foreign");
Services.prefs.setBoolPref("social.remote-install.enabled", true);
runSocialTests(tests, undefined, undefined, function () {
Services.prefs.clearUserPref("social.remote-install.enabled");
ok(!Services.prefs.prefHasUserValue(prefname), "manifest is not in user-prefs");
// just in case the tests failed, clear these here as well
Services.prefs.clearUserPref("social.directories");
finish();
});
}
function installListener(next, aManifest) {
let expectEvent = "onInstalling";
let prefname = getManifestPrefname(aManifest);
// wait for the actual removal to call next
SocialService.registerProviderListener(function providerListener(topic, origin, providers) {
if (topic == "provider-disabled") {
SocialService.unregisterProviderListener(providerListener);
is(origin, aManifest.origin, "provider disabled");
executeSoon(next);
}
});
return {
onInstalling: function(addon) {
is(expectEvent, "onInstalling", "install started");
is(addon.manifest.origin, aManifest.origin, "provider about to be installed");
ok(!Services.prefs.prefHasUserValue(prefname), "manifest is not in user-prefs");
expectEvent = "onInstalled";
},
onInstalled: function(addon) {
is(addon.manifest.origin, aManifest.origin, "provider installed");
ok(addon.installDate.getTime() > 0, "addon has installDate");
ok(addon.updateDate.getTime() > 0, "addon has updateDate");
ok(Services.prefs.prefHasUserValue(prefname), "manifest is in user-prefs");
expectEvent = "onUninstalling";
},
onUninstalling: function(addon) {
is(expectEvent, "onUninstalling", "uninstall started");
is(addon.manifest.origin, aManifest.origin, "provider about to be uninstalled");
ok(Services.prefs.prefHasUserValue(prefname), "manifest is in user-prefs");
expectEvent = "onUninstalled";
},
onUninstalled: function(addon) {
is(expectEvent, "onUninstalled", "provider has been uninstalled");
is(addon.manifest.origin, aManifest.origin, "provider uninstalled");
ok(!Services.prefs.prefHasUserValue(prefname), "manifest is not in user-prefs");
AddonManager.removeAddonListener(this);
}
};
}
var tests = {
testHTTPInstallFailure: function(next) {
let installFrom = "http://example.com";
is(SocialService.getOriginActivationType(installFrom), "foreign", "testing foriegn install");
let data = {
origin: installFrom,
url: installFrom+"/activate",
manifest: manifest,
window: window
}
Social.installProvider(data, function(addonManifest) {
ok(!addonManifest, "unable to install provider over http");
next();
});
},
testAddonEnableToggle: function(next) {
let expectEvent;
let prefname = getManifestPrefname(manifest);
let listener = {
onEnabled: function(addon) {
is(expectEvent, "onEnabled", "provider onEnabled");
ok(!addon.userDisabled, "provider enabled");
executeSoon(function() {
expectEvent = "onDisabling";
addon.userDisabled = true;
});
},
onEnabling: function(addon) {
is(expectEvent, "onEnabling", "provider onEnabling");
expectEvent = "onEnabled";
},
onDisabled: function(addon) {
is(expectEvent, "onDisabled", "provider onDisabled");
ok(addon.userDisabled, "provider disabled");
AddonManager.removeAddonListener(listener);
// clear the provider user-level pref
Services.prefs.clearUserPref(prefname);
executeSoon(next);
},
onDisabling: function(addon) {
is(expectEvent, "onDisabling", "provider onDisabling");
expectEvent = "onDisabled";
}
};
AddonManager.addAddonListener(listener);
// we're only testing enable disable, so we quickly set the user-level pref
// for this provider and test enable/disable toggling
setManifestPref(prefname, manifest);
ok(Services.prefs.prefHasUserValue(prefname), "manifest is in user-prefs");
AddonManager.getAddonsByTypes(["service"], function(addons) {
for (let addon of addons) {
if (addon.userDisabled) {
expectEvent = "onEnabling";
addon.userDisabled = false;
// only test with one addon
return;
}
}
ok(false, "no addons toggled");
next();
});
},
testProviderEnableToggle: function(next) {
// enable and disabel a provider from the SocialService interface, check
// that the addon manager is updated
let expectEvent;
let prefname = getManifestPrefname(manifest);
let listener = {
onEnabled: function(addon) {
is(expectEvent, "onEnabled", "provider onEnabled");
is(addon.manifest.origin, manifest.origin, "provider enabled");
ok(!addon.userDisabled, "provider !userDisabled");
},
onEnabling: function(addon) {
is(expectEvent, "onEnabling", "provider onEnabling");
is(addon.manifest.origin, manifest.origin, "provider about to be enabled");
expectEvent = "onEnabled";
},
onDisabled: function(addon) {
is(expectEvent, "onDisabled", "provider onDisabled");
is(addon.manifest.origin, manifest.origin, "provider disabled");
ok(addon.userDisabled, "provider userDisabled");
},
onDisabling: function(addon) {
is(expectEvent, "onDisabling", "provider onDisabling");
is(addon.manifest.origin, manifest.origin, "provider about to be disabled");
expectEvent = "onDisabled";
}
};
AddonManager.addAddonListener(listener);
expectEvent = "onEnabling";
setManifestPref(prefname, manifest);
SocialService.enableProvider(manifest.origin, function(provider) {
expectEvent = "onDisabling";
SocialService.disableProvider(provider.origin, function() {
AddonManager.removeAddonListener(listener);
Services.prefs.clearUserPref(prefname);
next();
});
});
},
testDirectoryInstall: function(next) {
AddonManager.addAddonListener(installListener(next, manifest2));
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown").then(() => {
let panel = document.getElementById("servicesInstall-notification");
info("servicesInstall-notification panel opened");
panel.button.click();
});
Services.prefs.setCharPref("social.directories", manifest2.origin);
is(SocialService.getOriginActivationType(manifest2.origin), "directory", "testing directory install");
let data = {
origin: manifest2.origin,
url: manifest2.origin + "/directory",
manifest: manifest2,
window: window
}
Social.installProvider(data, function(addonManifest) {
Services.prefs.clearUserPref("social.directories");
SocialService.enableProvider(addonManifest.origin, function(provider) {
Social.uninstallProvider(addonManifest.origin);
});
});
}
}

View file

@ -0,0 +1,211 @@
/* 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/. */
// a place for miscellaneous social tests
var SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul";
var blocklistURL = "http://example.com/browser/browser/base/content/test/social/blocklist.xml";
var manifest = { // normal provider
name: "provider ok",
origin: "https://example.com",
shareURL: "https://example.com/browser/browser/base/content/test/social/social_share.html",
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
};
var manifest_bad = { // normal provider
name: "provider blocked",
origin: "https://test1.example.com",
shareURL: "https://test1.example.com/browser/browser/base/content/test/social/social_share.html",
iconURL: "https://test1.example.com/browser/browser/base/content/test/general/moz.png"
};
// blocklist testing
function updateBlocklist() {
var blocklistNotifier = Cc["@mozilla.org/extensions/blocklist;1"]
.getService(Ci.nsITimerCallback);
let promise = promiseObserverNotified("blocklist-updated");
blocklistNotifier.notify(null);
return promise;
}
var _originalTestBlocklistURL = null;
function setAndUpdateBlocklist(aURL) {
if (!_originalTestBlocklistURL)
_originalTestBlocklistURL = Services.prefs.getCharPref("extensions.blocklist.url");
Services.prefs.setCharPref("extensions.blocklist.url", aURL);
return updateBlocklist();
}
function resetBlocklist() {
// XXX - this has "forked" from the head.js helpers in our parent directory :(
// But let's reuse their blockNoPlugins.xml. Later, we should arrange to
// use their head.js helpers directly
let noBlockedURL = "http://example.com/browser/browser/base/content/test/plugins/blockNoPlugins.xml";
return new Promise(resolve => {
setAndUpdateBlocklist(noBlockedURL).then(() => {
Services.prefs.setCharPref("extensions.blocklist.url", _originalTestBlocklistURL);
resolve();
});
});
}
function test() {
waitForExplicitFinish();
// turn on logging for nsBlocklistService.js
Services.prefs.setBoolPref("extensions.logging.enabled", true);
registerCleanupFunction(function () {
Services.prefs.clearUserPref("extensions.logging.enabled");
});
runSocialTests(tests, undefined, undefined, function () {
resetBlocklist().then(finish); // restore to original pref
});
}
var tests = {
testSimpleBlocklist: function(next) {
// this really just tests adding and clearing our blocklist for later tests
setAndUpdateBlocklist(blocklistURL).then(() => {
ok(Services.blocklist.isAddonBlocklisted(SocialService.createWrapper(manifest_bad)), "blocking 'blocked'");
ok(!Services.blocklist.isAddonBlocklisted(SocialService.createWrapper(manifest)), "not blocking 'good'");
resetBlocklist().then(() => {
ok(!Services.blocklist.isAddonBlocklisted(SocialService.createWrapper(manifest_bad)), "blocklist cleared");
next();
});
});
},
testAddingNonBlockedProvider: function(next) {
function finishTest(isgood) {
ok(isgood, "adding non-blocked provider ok");
Services.prefs.clearUserPref("social.manifest.good");
resetBlocklist().then(next);
}
setManifestPref("social.manifest.good", manifest);
setAndUpdateBlocklist(blocklistURL).then(() => {
try {
SocialService.addProvider(manifest, function(provider) {
try {
SocialService.disableProvider(provider.origin, function() {
ok(true, "added and removed provider");
finishTest(true);
});
} catch (e) {
ok(false, "SocialService.disableProvider threw exception: " + e);
finishTest(false);
}
});
} catch (e) {
ok(false, "SocialService.addProvider threw exception: " + e);
finishTest(false);
}
});
},
testAddingBlockedProvider: function(next) {
function finishTest(good) {
ok(good, "Unable to add blocklisted provider");
Services.prefs.clearUserPref("social.manifest.blocked");
resetBlocklist().then(next);
}
setManifestPref("social.manifest.blocked", manifest_bad);
setAndUpdateBlocklist(blocklistURL).then(() => {
try {
SocialService.addProvider(manifest_bad, function(provider) {
SocialService.disableProvider(provider.origin, function() {
ok(false, "SocialService.addProvider should throw blocklist exception");
finishTest(false);
});
});
} catch (e) {
ok(true, "SocialService.addProvider should throw blocklist exception: " + e);
finishTest(true);
}
});
},
testInstallingBlockedProvider: function(next) {
function finishTest(good) {
ok(good, "Unable to install blocklisted provider");
resetBlocklist().then(next);
}
let activationURL = manifest_bad.origin + "/browser/browser/base/content/test/social/social_activate.html"
setAndUpdateBlocklist(blocklistURL).then(() => {
try {
// expecting an exception when attempting to install a hard blocked
// provider
let data = {
origin: manifest_bad.origin,
url: activationURL,
manifest: manifest_bad,
window: window
}
Social.installProvider(data, function(addonManifest) {
finishTest(false);
});
} catch (e) {
finishTest(true);
}
});
},
testBlockingExistingProvider: function(next) {
let listener = {
_window: null,
onOpenWindow: function(aXULWindow) {
Services.wm.removeListener(this);
this._window = aXULWindow;
let domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
domwindow.addEventListener("load", function _load() {
domwindow.removeEventListener("load", _load, false);
domwindow.addEventListener("unload", function _unload() {
domwindow.removeEventListener("unload", _unload, false);
info("blocklist window was closed");
Services.wm.removeListener(listener);
next();
}, false);
is(domwindow.document.location.href, URI_EXTENSION_BLOCKLIST_DIALOG, "dialog opened and focused");
// wait until after load to cancel so the dialog has initalized. we
// don't want to accept here since that restarts the browser.
executeSoon(() => {
let cancelButton = domwindow.document.documentElement.getButton("cancel");
info("***** hit the cancel button\n");
cancelButton.doCommand();
});
}, false);
},
onCloseWindow: function(aXULWindow) { },
onWindowTitleChange: function(aXULWindow, aNewTitle) { }
};
Services.wm.addListener(listener);
setManifestPref("social.manifest.blocked", manifest_bad);
try {
SocialService.addProvider(manifest_bad, function(provider) {
// the act of blocking should cause a 'provider-disabled' notification
// from SocialService.
SocialService.registerProviderListener(function providerListener(topic, origin, providers) {
if (topic != "provider-disabled")
return;
SocialService.unregisterProviderListener(providerListener);
is(origin, provider.origin, "provider disabled");
SocialService.getProvider(provider.origin, function(p) {
ok(p == null, "blocklisted provider disabled");
Services.prefs.clearUserPref("social.manifest.blocked");
resetBlocklist();
});
});
// no callback - the act of updating should cause the listener above
// to fire.
setAndUpdateBlocklist(blocklistURL);
});
} catch (e) {
ok(false, "unable to add provider " + e);
next();
}
}
}

View file

@ -0,0 +1,396 @@
var SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
var baseURL = "https://example.com/browser/browser/base/content/test/social/";
var manifest = { // normal provider
name: "provider 1",
origin: "https://example.com",
iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png",
shareURL: "https://example.com/browser/browser/base/content/test/social/share.html"
};
var activationPage = "https://example.com/browser/browser/base/content/test/social/share_activate.html";
function sendActivationEvent(subframe) {
// hack Social.lastEventReceived so we don't hit the "too many events" check.
Social.lastEventReceived = 0;
let doc = subframe.contentDocument;
// if our test has a frame, use it
let button = doc.getElementById("activation");
ok(!!button, "got the activation button");
EventUtils.synthesizeMouseAtCenter(button, {}, doc.defaultView);
}
function test() {
waitForExplicitFinish();
Services.prefs.setCharPref("social.shareDirectory", activationPage);
let frameScript = "data:,(" + function frame_script() {
addEventListener("OpenGraphData", function (aEvent) {
sendAsyncMessage("sharedata", aEvent.detail);
}, true, true);
/* bug 1042991, ensure history is available by calling history.back on close */
addMessageListener("closeself", function(e) {
content.history.back();
content.close();
}, true);
/* if text is entered into field, onbeforeunload will cause a modal dialog
unless dialogs have been disabled for the iframe. */
content.onbeforeunload = function(e) {
return 'FAIL.';
};
}.toString() + ")();";
let mm = getGroupMessageManager("social");
mm.loadFrameScript(frameScript, true);
// Animation on the panel can cause intermittent failures such as bug 1115131.
SocialShare.panel.setAttribute("animate", "false");
registerCleanupFunction(function () {
SocialShare.panel.removeAttribute("animate");
mm.removeDelayedFrameScript(frameScript);
Services.prefs.clearUserPref("social.directories");
Services.prefs.clearUserPref("social.shareDirectory");
Services.prefs.clearUserPref("social.share.activationPanelEnabled");
});
runSocialTests(tests, undefined, function(next) {
let shareButton = SocialShare.shareButton;
if (shareButton) {
CustomizableUI.removeWidgetFromArea("social-share-button", CustomizableUI.AREA_NAVBAR)
shareButton.remove();
}
next();
});
}
var corpus = [
{
url: baseURL+"opengraph/opengraph.html",
options: {
// og:title
title: ">This is my title<",
// og:description
description: "A test corpus file for open graph tags we care about",
// medium: this.getPageMedium(),
// source: this.getSourceURL(),
// og:url
url: "https://www.mozilla.org/",
// shortUrl: this.getShortURL(),
// og:image
previews:["https://www.mozilla.org/favicon.png"],
// og:site_name
siteName: ">My simple test page<"
}
},
{
// tests that og:url doesn't override the page url if it is bad
url: baseURL+"opengraph/og_invalid_url.html",
options: {
description: "A test corpus file for open graph tags passing a bad url",
url: baseURL+"opengraph/og_invalid_url.html",
previews: [],
siteName: "Evil chrome delivering website"
}
},
{
url: baseURL+"opengraph/shorturl_link.html",
options: {
previews: ["http://example.com/1234/56789.jpg"],
url: "http://www.example.com/photos/56789/",
shortUrl: "http://imshort/p/abcde"
}
},
{
url: baseURL+"opengraph/shorturl_linkrel.html",
options: {
previews: ["http://example.com/1234/56789.jpg"],
url: "http://www.example.com/photos/56789/",
shortUrl: "http://imshort/p/abcde"
}
},
{
url: baseURL+"opengraph/shortlink_linkrel.html",
options: {
previews: ["http://example.com/1234/56789.jpg"],
url: "http://www.example.com/photos/56789/",
shortUrl: "http://imshort/p/abcde"
}
}
];
function hasoptions(testOptions, options) {
for (let option in testOptions) {
let data = testOptions[option];
info("data: "+JSON.stringify(data));
let message_data = options[option];
info("message_data: "+JSON.stringify(message_data));
if (Array.isArray(data)) {
// the message may have more array elements than we are testing for, this
// is ok since some of those are hard to test. So we just test that
// anything in our test data IS in the message.
ok(Array.every(data, function(item) { return message_data.indexOf(item) >= 0 }), "option "+option);
} else {
is(message_data, data, "option "+option);
}
}
}
var tests = {
testShareDisabledOnActivation: function(next) {
// starting on about:blank page, share should be visible but disabled when
// adding provider
is(gBrowser.currentURI.spec, "about:blank");
// initialize the button into the navbar
CustomizableUI.addWidgetToArea("social-share-button", CustomizableUI.AREA_NAVBAR);
// ensure correct state
SocialUI.onCustomizeEnd(window);
SocialService.addProvider(manifest, function(provider) {
is(SocialUI.enabled, true, "SocialUI is enabled");
checkSocialUI();
// share should not be enabled since we only have about:blank page
let shareButton = SocialShare.shareButton;
// verify the attribute for proper css
is(shareButton.getAttribute("disabled"), "true", "share button attribute is disabled");
// button should be visible
is(shareButton.hidden, false, "share button is visible");
SocialService.disableProvider(manifest.origin, next);
});
},
testShareEnabledOnActivation: function(next) {
// starting from *some* page, share should be visible and enabled when
// activating provider
// initialize the button into the navbar
CustomizableUI.addWidgetToArea("social-share-button", CustomizableUI.AREA_NAVBAR);
// ensure correct state
SocialUI.onCustomizeEnd(window);
let testData = corpus[0];
BrowserTestUtils.openNewForegroundTab(gBrowser, testData.url).then(tab => {
SocialService.addProvider(manifest, function(provider) {
is(SocialUI.enabled, true, "SocialUI is enabled");
checkSocialUI();
// share should not be enabled since we only have about:blank page
let shareButton = SocialShare.shareButton;
// verify the attribute for proper css
ok(!shareButton.hasAttribute("disabled"), "share button is enabled");
// button should be visible
is(shareButton.hidden, false, "share button is visible");
BrowserTestUtils.removeTab(tab).then(next);
});
});
},
testSharePage: function(next) {
let testTab;
let testIndex = 0;
let testData = corpus[testIndex++];
// initialize the button into the navbar
CustomizableUI.addWidgetToArea("social-share-button", CustomizableUI.AREA_NAVBAR);
// ensure correct state
SocialUI.onCustomizeEnd(window);
let mm = getGroupMessageManager("social");
mm.addMessageListener("sharedata", function handler(msg) {
BrowserTestUtils.removeTab(testTab).then(() => {
hasoptions(testData.options, JSON.parse(msg.data));
testData = corpus[testIndex++];
BrowserTestUtils.waitForCondition(() => { return SocialShare.currentShare == null; }, "share panel closed").then(() => {
if (testData) {
runOneTest();
} else {
mm.removeMessageListener("sharedata", handler);
SocialService.disableProvider(manifest.origin, next);
}
});
SocialShare.iframe.messageManager.sendAsyncMessage("closeself", {});
});
});
function runOneTest() {
BrowserTestUtils.openNewForegroundTab(gBrowser, testData.url).then(tab => {
testTab = tab;
let shareButton = SocialShare.shareButton;
// verify the attribute for proper css
ok(!shareButton.hasAttribute("disabled"), "share button is enabled");
// button should be visible
is(shareButton.hidden, false, "share button is visible");
SocialShare.sharePage(manifest.origin);
});
}
executeSoon(runOneTest);
},
testShareMicroformats: function(next) {
// initialize the button into the navbar
CustomizableUI.addWidgetToArea("social-share-button", CustomizableUI.AREA_NAVBAR);
// ensure correct state
SocialUI.onCustomizeEnd(window);
SocialService.addProvider(manifest, function(provider) {
let target, testTab;
let expecting = JSON.stringify({
"url": "https://example.com/browser/browser/base/content/test/social/microformats.html",
"title": "Raspberry Pi Page",
"previews": ["https://example.com/someimage.jpg"],
"microformats": {
"items": [{
"type": ["h-product"],
"properties": {
"name": ["Raspberry Pi"],
"photo": ["https://example.com/someimage.jpg"],
"description": [{
"value": "The Raspberry Pi is a credit-card sized computer that plugs into your TV and a keyboard. It's a capable little PC which can be used for many of the things that your desktop PC does, like spreadsheets, word-processing and games. It also plays high-definition video. We want to see it being used by kids all over the world to learn programming.",
"html": "The Raspberry Pi is a credit-card sized computer that plugs into your TV and a keyboard. It's a capable little PC which can be used for many of the things that your desktop PC does, like spreadsheets, word-processing and games. It also plays high-definition video. We want to see it being used by kids all over the world to learn programming."
}
],
"url": ["https://example.com/"],
"price": ["29.95"],
"review": [{
"value": "4.5 out of 5",
"type": ["h-review"],
"properties": {
"rating": ["4.5"]
}
}
],
"category": ["Computer", "Education"]
}
}
],
"rels": {
"tag": ["https://example.com/wiki/computer", "https://example.com/wiki/education"]
},
"rel-urls": {
"https://example.com/wiki/computer": {
"text": "Computer",
"rels": ["tag"]
},
"https://example.com/wiki/education": {
"text": "Education",
"rels": ["tag"]
}
}
}
});
let mm = getGroupMessageManager("social");
mm.addMessageListener("sharedata", function handler(msg) {
is(msg.data, expecting, "microformats data ok");
BrowserTestUtils.waitForCondition(() => { return SocialShare.currentShare == null; },
"share panel closed").then(() => {
mm.removeMessageListener("sharedata", handler);
BrowserTestUtils.removeTab(testTab).then(() => {
SocialService.disableProvider(manifest.origin, next);
});
});
SocialShare.iframe.messageManager.sendAsyncMessage("closeself", {});
});
let url = "https://example.com/browser/browser/base/content/test/social/microformats.html"
BrowserTestUtils.openNewForegroundTab(gBrowser, url).then(tab => {
testTab = tab;
let shareButton = SocialShare.shareButton;
// verify the attribute for proper css
ok(!shareButton.hasAttribute("disabled"), "share button is enabled");
// button should be visible
is(shareButton.hidden, false, "share button is visible");
let doc = tab.linkedBrowser.contentDocument;
target = doc.getElementById("simple-hcard");
SocialShare.sharePage(manifest.origin, null, target);
});
});
},
testSharePanelActivation: function(next) {
let testTab;
// cleared in the cleanup function
Services.prefs.setCharPref("social.directories", "https://example.com");
Services.prefs.setBoolPref("social.share.activationPanelEnabled", true);
// make the iframe so we can wait on the load
SocialShare._createFrame();
let iframe = SocialShare.iframe;
// initialize the button into the navbar
CustomizableUI.addWidgetToArea("social-share-button", CustomizableUI.AREA_NAVBAR);
// ensure correct state
SocialUI.onCustomizeEnd(window);
ensureFrameLoaded(iframe).then(() => {
let subframe = iframe.contentDocument.getElementById("activation-frame");
ensureFrameLoaded(subframe, activationPage).then(() => {
is(subframe.contentDocument.location.href, activationPage, "activation page loaded");
promiseObserverNotified("social:provider-enabled").then(() => {
let mm = getGroupMessageManager("social");
mm.addMessageListener("sharedata", function handler(msg) {
ok(true, "share completed");
BrowserTestUtils.waitForCondition(() => { return SocialShare.currentShare == null; },
"share panel closed").then(() => {
BrowserTestUtils.removeTab(testTab).then(() => {
mm.removeMessageListener("sharedata", handler);
SocialService.uninstallProvider(manifest.origin, next);
});
});
SocialShare.iframe.messageManager.sendAsyncMessage("closeself", {});
});
});
sendActivationEvent(subframe);
});
});
BrowserTestUtils.openNewForegroundTab(gBrowser, activationPage).then(tab => {
let shareButton = SocialShare.shareButton;
// verify the attribute for proper css
ok(!shareButton.hasAttribute("disabled"), "share button is enabled");
// button should be visible
is(shareButton.hidden, false, "share button is visible");
testTab = tab;
SocialShare.sharePage();
});
},
testSharePanelDialog: function(next) {
let testTab;
// initialize the button into the navbar
CustomizableUI.addWidgetToArea("social-share-button", CustomizableUI.AREA_NAVBAR);
// ensure correct state
SocialUI.onCustomizeEnd(window);
SocialShare._createFrame();
SocialService.addProvider(manifest, () => {
BrowserTestUtils.openNewForegroundTab(gBrowser, activationPage).then(tab => {
ensureFrameLoaded(SocialShare.iframe).then(() => {
// send keys to the input field. An unexpected failure will happen
// if the onbeforeunload handler is fired.
EventUtils.sendKey("f");
EventUtils.sendKey("a");
EventUtils.sendKey("i");
EventUtils.sendKey("l");
SocialShare.panel.addEventListener("popuphidden", function hidden(evt) {
SocialShare.panel.removeEventListener("popuphidden", hidden);
let topwin = Services.wm.getMostRecentWindow(null);
is(topwin, window, "no dialog is open");
BrowserTestUtils.removeTab(testTab).then(() => {
SocialService.disableProvider(manifest.origin, next);
});
});
SocialShare.iframe.messageManager.sendAsyncMessage("closeself", {});
});
let shareButton = SocialShare.shareButton;
// verify the attribute for proper css
ok(!shareButton.hasAttribute("disabled"), "share button is enabled");
// button should be visible
is(shareButton.hidden, false, "share button is visible");
testTab = tab;
SocialShare.sharePage();
});
});
}
}

View file

@ -0,0 +1,270 @@
/* 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/. */
//
// Whitelisting this test.
// As part of bug 1077403, the leaking uncaught rejection should be fixed.
//
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: Assert is null");
var SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
var tabsToRemove = [];
function removeProvider(provider) {
return new Promise(resolve => {
// a full install sets the manifest into a pref, addProvider alone doesn't,
// make sure we uninstall if the manifest was added.
if (provider.manifest) {
SocialService.uninstallProvider(provider.origin, resolve);
} else {
SocialService.disableProvider(provider.origin, resolve);
}
});
}
function postTestCleanup(callback) {
Task.spawn(function* () {
// any tabs opened by the test.
for (let tab of tabsToRemove) {
yield BrowserTestUtils.removeTab(tab);
}
tabsToRemove = [];
// all the providers may have been added.
while (Social.providers.length > 0) {
yield removeProvider(Social.providers[0]);
}
}).then(callback);
}
function newTab(url) {
return new Promise(resolve => {
BrowserTestUtils.openNewForegroundTab(gBrowser, url).then(tab => {
tabsToRemove.push(tab);
resolve(tab);
});
});
}
function sendActivationEvent(tab, callback, nullManifest) {
// hack Social.lastEventReceived so we don't hit the "too many events" check.
Social.lastEventReceived = 0;
BrowserTestUtils.synthesizeMouseAtCenter("#activation", {}, tab.linkedBrowser);
executeSoon(callback);
}
function activateProvider(domain, callback, nullManifest) {
let activationURL = domain+"/browser/browser/base/content/test/social/social_activate_basic.html"
newTab(activationURL).then(tab => {
sendActivationEvent(tab, callback, nullManifest);
});
}
function activateIFrameProvider(domain, callback) {
let activationURL = domain+"/browser/browser/base/content/test/social/social_activate_iframe.html"
newTab(activationURL).then(tab => {
sendActivationEvent(tab, callback, false);
});
}
function waitForProviderLoad(origin) {
return Promise.all([
ensureFrameLoaded(gBrowser, origin + "/browser/browser/base/content/test/social/social_postActivation.html"),
]);
}
function getAddonItemInList(aId, aList) {
var item = aList.firstChild;
while (item) {
if ("mAddon" in item && item.mAddon.id == aId) {
aList.ensureElementIsVisible(item);
return item;
}
item = item.nextSibling;
}
return null;
}
function clickAddonRemoveButton(tab, aCallback) {
AddonManager.getAddonsByTypes(["service"], function(aAddons) {
let addon = aAddons[0];
let doc = tab.linkedBrowser.contentDocument;
let list = doc.getElementById("addon-list");
let item = getAddonItemInList(addon.id, list);
let button = item._removeBtn;
isnot(button, null, "Should have a remove button");
ok(!button.disabled, "Button should not be disabled");
// uninstall happens after about:addons tab is closed, so we wait on
// disabled
promiseObserverNotified("social:provider-disabled").then(() => {
is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling");
executeSoon(function() { aCallback(addon); });
});
BrowserTestUtils.synthesizeMouseAtCenter(button, {}, tab.linkedBrowser);
});
}
function activateOneProvider(manifest, finishActivation, aCallback) {
info("activating provider "+manifest.name);
let panel = document.getElementById("servicesInstall-notification");
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown").then(() => {
ok(!panel.hidden, "servicesInstall-notification panel opened");
if (finishActivation)
panel.button.click();
else
panel.closebutton.click();
});
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popuphidden").then(() => {
ok(panel.hidden, "servicesInstall-notification panel hidden");
if (!finishActivation) {
ok(panel.hidden, "activation panel is not showing");
executeSoon(aCallback);
} else {
waitForProviderLoad(manifest.origin).then(() => {
checkSocialUI();
executeSoon(aCallback);
});
}
});
// the test will continue as the popup events fire...
activateProvider(manifest.origin, function() {
info("waiting on activation panel to open/close...");
});
}
var gTestDomains = ["https://example.com", "https://test1.example.com", "https://test2.example.com"];
var gProviders = [
{
name: "provider 1",
origin: "https://example.com",
shareURL: "https://example.com/browser/browser/base/content/test/social/social_share.html?provider1",
iconURL: "chrome://branding/content/icon48.png"
},
{
name: "provider 2",
origin: "https://test1.example.com",
shareURL: "https://test1.example.com/browser/browser/base/content/test/social/social_share.html?provider2",
iconURL: "chrome://branding/content/icon64.png"
},
{
name: "provider 3",
origin: "https://test2.example.com",
shareURL: "https://test2.example.com/browser/browser/base/content/test/social/social_share.html?provider2",
iconURL: "chrome://branding/content/about-logo.png"
}
];
function test() {
PopupNotifications.panel.setAttribute("animate", "false");
registerCleanupFunction(function () {
PopupNotifications.panel.removeAttribute("animate");
});
waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.ipc.processCount", 1]]}, () => {
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");
let panel = document.getElementById("servicesInstall-notification");
ok(panel.hidden, "activation panel still hidden");
checkSocialUI();
Services.prefs.clearUserPref("social.remote-install.enabled");
next();
});
},
testIFrameActivation: function(next) {
activateIFrameProvider(gTestDomains[0], function() {
is(SocialUI.enabled, false, "SocialUI is not enabled");
let panel = document.getElementById("servicesInstall-notification");
ok(panel.hidden, "activation panel still hidden");
checkSocialUI();
next();
});
},
testActivationFirstProvider: function(next) {
// first up we add a manifest entry for a single provider.
activateOneProvider(gProviders[0], false, function() {
// we deactivated leaving no providers left, so Social is disabled.
checkSocialUI();
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
SocialService.addProvider(gProviders[0], function() {
SocialService.addProvider(gProviders[1], function() {
checkSocialUI();
// activate the last provider.
activateOneProvider(gProviders[2], false, function() {
// we deactivated - the first provider should be enabled.
checkSocialUI();
next();
});
});
});
},
testAddonManagerDoubleInstall: function(next) {
// Create a new tab and load about:addons
let addonsTab = gBrowser.addTab();
gBrowser.selectedTab = addonsTab;
BrowserOpenAddonsMgr('addons://list/service');
gBrowser.selectedBrowser.addEventListener("load", function tabLoad() {
gBrowser.selectedBrowser.removeEventListener("load", tabLoad, true);
is(addonsTab.linkedBrowser.currentURI.spec, "about:addons", "about:addons should load into blank tab.");
activateOneProvider(gProviders[0], true, function() {
info("first activation completed");
is(gBrowser.contentDocument.location.href, gProviders[0].origin + "/browser/browser/base/content/test/social/social_postActivation.html", "postActivationURL loaded");
BrowserTestUtils.removeTab(gBrowser.selectedTab).then(() => {
is(gBrowser.contentDocument.location.href, gProviders[0].origin + "/browser/browser/base/content/test/social/social_activate_basic.html", "activation page selected");
BrowserTestUtils.removeTab(gBrowser.selectedTab).then(() => {
tabsToRemove.pop();
// uninstall the provider
clickAddonRemoveButton(addonsTab, function(addon) {
checkSocialUI();
activateOneProvider(gProviders[0], true, function() {
info("second activation completed");
is(gBrowser.contentDocument.location.href, gProviders[0].origin + "/browser/browser/base/content/test/social/social_postActivation.html", "postActivationURL loaded");
BrowserTestUtils.removeTab(gBrowser.selectedTab).then(() => {
// after closing the addons tab, verify provider is still installed
AddonManager.getAddonsByTypes(["service"], function(aAddons) {
is(aAddons.length, 1, "there can be only one");
let doc = addonsTab.linkedBrowser.contentDocument;
let list = doc.getElementById("addon-list");
is(list.childNodes.length, 1, "only one addon is displayed");
BrowserTestUtils.removeTab(addonsTab).then(next);
});
});
});
});
});
});
});
}, true);
}
}

View file

@ -0,0 +1,273 @@
/* 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/. */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
"resource://gre/modules/PlacesUtils.jsm");
function promiseObserverNotified(aTopic) {
return new Promise(resolve => {
Services.obs.addObserver(function onNotification(aSubject, aTopic, aData) {
dump("notification promised "+aTopic);
Services.obs.removeObserver(onNotification, aTopic);
TestUtils.executeSoon(() => resolve({subject: aSubject, data: aData}));
}, aTopic, false);
});
}
// Check that a specified (string) URL hasn't been "remembered" (ie, is not
// in history, will not appear in about:newtab or auto-complete, etc.)
function promiseSocialUrlNotRemembered(url) {
return new Promise(resolve => {
let uri = Services.io.newURI(url, null, null);
PlacesUtils.asyncHistory.isURIVisited(uri, function(aURI, aIsVisited) {
ok(!aIsVisited, "social URL " + url + " should not be in global history");
resolve();
});
});
}
var gURLsNotRemembered = [];
function checkProviderPrefsEmpty(isError) {
let MANIFEST_PREFS = Services.prefs.getBranch("social.manifest.");
let prefs = MANIFEST_PREFS.getChildList("", []);
let c = 0;
for (let pref of prefs) {
if (MANIFEST_PREFS.prefHasUserValue(pref)) {
info("provider [" + pref + "] manifest left installed from previous test");
c++;
}
}
is(c, 0, "all provider prefs uninstalled from previous test");
is(Social.providers.length, 0, "all providers uninstalled from previous test " + Social.providers.length);
}
function defaultFinishChecks() {
checkProviderPrefsEmpty(true);
finish();
}
function runSocialTestWithProvider(manifest, callback, finishcallback) {
let SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
let manifests = Array.isArray(manifest) ? manifest : [manifest];
// Check that none of the provider's content ends up in history.
function* finishCleanUp() {
for (let i = 0; i < manifests.length; i++) {
let m = manifests[i];
for (let what of ['iconURL', 'shareURL']) {
if (m[what]) {
yield promiseSocialUrlNotRemembered(m[what]);
}
}
}
for (let i = 0; i < gURLsNotRemembered.length; i++) {
yield promiseSocialUrlNotRemembered(gURLsNotRemembered[i]);
}
gURLsNotRemembered = [];
}
info("runSocialTestWithProvider: " + manifests.toSource());
let finishCount = 0;
function finishIfDone(callFinish) {
finishCount++;
if (finishCount == manifests.length)
Task.spawn(finishCleanUp).then(finishcallback || defaultFinishChecks);
}
function removeAddedProviders(cleanup) {
manifests.forEach(function (m) {
// If we're "cleaning up", don't call finish when done.
let callback = cleanup ? function () {} : finishIfDone;
// Similarly, if we're cleaning up, catch exceptions from removeProvider
let removeProvider = SocialService.disableProvider.bind(SocialService);
if (cleanup) {
removeProvider = function (origin, cb) {
try {
SocialService.disableProvider(origin, cb);
} catch (ex) {
// Ignore "provider doesn't exist" errors.
if (ex.message.indexOf("SocialService.disableProvider: no provider with origin") == 0)
return;
info("Failed to clean up provider " + origin + ": " + ex);
}
}
}
removeProvider(m.origin, callback);
});
}
function finishSocialTest(cleanup) {
removeAddedProviders(cleanup);
}
let providersAdded = 0;
manifests.forEach(function (m) {
SocialService.addProvider(m, function(provider) {
providersAdded++;
info("runSocialTestWithProvider: provider added");
// we want to set the first specified provider as the UI's provider
if (provider.origin == manifests[0].origin) {
firstProvider = provider;
}
// If we've added all the providers we need, call the callback to start
// the tests (and give it a callback it can call to finish them)
if (providersAdded == manifests.length) {
registerCleanupFunction(function () {
finishSocialTest(true);
});
BrowserTestUtils.waitForCondition(() => provider.enabled,
"providers added and enabled").then(() => {
info("provider has been enabled");
callback(finishSocialTest);
});
}
});
});
}
function runSocialTests(tests, cbPreTest, cbPostTest, cbFinish) {
let testIter = (function*() {
for (let name in tests) {
if (tests.hasOwnProperty(name)) {
yield [name, tests[name]];
}
}
})();
let providersAtStart = Social.providers.length;
info("runSocialTests: start test run with " + providersAtStart + " providers");
window.focus();
if (cbPreTest === undefined) {
cbPreTest = function(cb) { cb() };
}
if (cbPostTest === undefined) {
cbPostTest = function(cb) { cb() };
}
function runNextTest() {
let result = testIter.next();
if (result.done) {
// out of items:
(cbFinish || defaultFinishChecks)();
is(providersAtStart, Social.providers.length,
"runSocialTests: finish test run with " + Social.providers.length + " providers");
return;
}
let [name, func] = result.value;
// We run on a timeout to help keep the debug messages sane.
executeSoon(function() {
function cleanupAndRunNextTest() {
info("sub-test " + name + " complete");
cbPostTest(runNextTest);
}
cbPreTest(function() {
info("pre-test: starting with " + Social.providers.length + " providers");
info("sub-test " + name + " starting");
try {
func.call(tests, cleanupAndRunNextTest);
} catch (ex) {
ok(false, "sub-test " + name + " failed: " + ex.toString() +"\n"+ex.stack);
cleanupAndRunNextTest();
}
})
});
}
runNextTest();
}
// A fairly large hammer which checks all aspects of the SocialUI for
// internal consistency.
function checkSocialUI(win) {
let SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
// if we have enabled providers, we should also have instances of those
// providers
if (SocialService.hasEnabledProviders) {
ok(Social.providers.length > 0, "providers are enabled");
} else {
is(Social.providers.length, 0, "providers are not enabled");
}
}
function setManifestPref(name, manifest) {
let string = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
string.data = JSON.stringify(manifest);
Services.prefs.setComplexValue(name, Ci.nsISupportsString, string);
}
function getManifestPrefname(aManifest) {
// is same as the generated name in SocialServiceInternal.getManifestPrefname
let originUri = Services.io.newURI(aManifest.origin, null, null);
return "social.manifest." + originUri.hostPort.replace('.', '-');
}
function ensureFrameLoaded(frame, uri) {
return new Promise(resolve => {
if (frame.contentDocument && frame.contentDocument.readyState == "complete" &&
(!uri || frame.contentDocument.location.href == uri)) {
resolve();
} else {
frame.addEventListener("load", function handler() {
if (uri && frame.contentDocument.location.href != uri)
return;
frame.removeEventListener("load", handler, true);
resolve()
}, true);
}
});
}
// Support for going on and offline.
// (via browser/base/content/test/browser_bookmark_titles.js)
var origProxyType = Services.prefs.getIntPref('network.proxy.type');
function toggleOfflineStatus(goOffline) {
// Bug 968887 fix. when going on/offline, wait for notification before continuing
return new Promise(resolve => {
if (!goOffline) {
Services.prefs.setIntPref('network.proxy.type', origProxyType);
}
if (goOffline != Services.io.offline) {
info("initial offline state " + Services.io.offline);
let expect = !Services.io.offline;
Services.obs.addObserver(function offlineChange(subject, topic, data) {
Services.obs.removeObserver(offlineChange, "network:offline-status-changed");
info("offline state changed to " + Services.io.offline);
is(expect, Services.io.offline, "network:offline-status-changed successful toggle");
resolve();
}, "network:offline-status-changed", false);
BrowserOffline.toggleOfflineStatus();
} else {
resolve();
}
if (goOffline) {
Services.prefs.setIntPref('network.proxy.type', 0);
// LOAD_FLAGS_BYPASS_CACHE isn't good enough. So clear the cache.
Services.cache2.clear();
}
});
}
function goOffline() {
// Simulate a network outage with offline mode. (Localhost is still
// accessible in offline mode, so disable the test proxy as well.)
return toggleOfflineStatus(true);
}
function goOnline(callback) {
return toggleOfflineStatus(false);
}

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<body>
<head><title>Raspberry Pi Page</title></head>
<div class="hproduct">
<h2 class="fn">Raspberry Pi</h2>
<img class="photo" src="https://example.com/someimage.jpg" />
<p class="description">The Raspberry Pi is a credit-card sized computer that plugs into your TV and a keyboard. It's a capable little PC which can be used for many of the things that your desktop PC does, like spreadsheets, word-processing and games. It also plays high-definition video. We want to see it being used by kids all over the world to learn programming.</p>
<a class="url" href="https://example.com/">More info about the Raspberry Pi</a>
<p class="price">29.95</p>
<p class="review hreview"><span id="test-review" class="rating">4.5</span> out of 5</p>
<p>Categories:
<a rel="tag" href="https://example.com/wiki/computer" class="category">Computer</a>,
<a rel="tag" href="https://example.com/wiki/education" class="category">Education</a>
</p>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

View file

@ -0,0 +1,11 @@
<html xmlns:og="http://ogp.me/ns#">
<head>
<meta property="og:url" content="chrome://browser/content/aboutDialog.xul"/>
<meta property="og:site_name" content="Evil chrome delivering website"/>
<meta property="og:description"
content="A test corpus file for open graph tags passing a bad url"/>
</head>
<body>
Open Graph Test Page
</body>
</html>

View file

@ -0,0 +1,13 @@
<html xmlns:og="http://ogp.me/ns#">
<head>
<meta property="og:title" content="&gt;This is my title&lt;"/>
<meta property="og:url" content="https://www.mozilla.org"/>
<meta property="og:image" content="https://www.mozilla.org/favicon.png"/>
<meta property="og:site_name" content="&#62;My simple test page&#60;"/>
<meta property="og:description"
content="A test corpus file for open graph tags we care about"/>
</head>
<body>
Open Graph Test Page
</body>
</html>

View file

@ -0,0 +1,10 @@
<html>
<head>
<link rel="image_src" href="http://example.com/1234/56789.jpg" id="image-src" />
<link id="canonicalurl" rel="canonical" href="http://www.example.com/photos/56789/" />
<link rel="shortlink" href="http://imshort/p/abcde" />
</head>
<body>
link[rel='shortlink']
</body>
</html>

View file

@ -0,0 +1,10 @@
<html>
<head>
<link rel="image_src" href="http://example.com/1234/56789.jpg" id="image-src" />
<link id="canonicalurl" rel="canonical" href="http://www.example.com/photos/56789/" />
<link id="shorturl" rev="canonical" type="text/html" href="http://imshort/p/abcde" />
</head>
<body>
link id="shorturl"
</body>
</html>

View file

@ -0,0 +1,25 @@
<html>
<head>
<title>Test Image</title>
<meta name="description" content="Iron man in a tutu" />
<meta name="title" content="Test Image" />
<meta name="medium" content="image" />
<link rel="image_src" href="http://example.com/1234/56789.jpg" id="image-src" />
<link id="canonicalurl" rel="canonical" href="http://www.example.com/photos/56789/" />
<link id="shorturl" href="http://imshort/p/abcde" />
<meta property="og:title" content="TestImage" />
<meta property="og:type" content="photos:photo" />
<meta property="og:url" content="http://www.example.com/photos/56789/" />
<meta property="og:site_name" content="My Photo Site" />
<meta property="og:description" content="Iron man in a tutu" />
<meta property="og:image" content="http://example.com/1234/56789.jpg" />
<meta property="og:image:width" content="480" />
<meta property="og:image:height" content="640" />
</head>
<body>
link[rel='shorturl']
</body>
</html>

View file

@ -0,0 +1,9 @@
<html>
<head>
<meta charset="utf-8">
</head>
<body onload="document.getElementById('testclose').focus()">
<p>This is a test social share window.</p>
<input id="testclose"/>
</body>
</html>

View file

@ -0,0 +1,35 @@
<html>
<!-- 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/. -->
<head>
<title>Activation test</title>
</head>
<script>
var data = {
// currently required
"name": "Demo Social Service",
// browser_share.js serves this page from "https://example.com"
"origin": "https://example.com",
"iconURL": "chrome://branding/content/icon16.png",
"icon32URL": "chrome://branding/content/favicon32.png",
"icon64URL": "chrome://branding/content/icon64.png",
"shareURL": "/browser/browser/base/content/test/social/share.html"
}
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, true)">Activate the share provider</button>
</body>
</html>

View file

@ -0,0 +1,41 @@
<html>
<head>
<meta charset="utf-8">
<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
"shareURL": "/browser/browser/base/content/test/social/social_share.html",
"postActivationURL": "/browser/browser/base/content/test/social/social_postActivation.html",
// 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>

View file

@ -0,0 +1,41 @@
<html>
<head>
<meta charset="utf-8">
<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
"shareURL": "/browser/browser/base/content/test/social/social_share.html",
"postActivationURL": "/browser/browser/base/content/test/social/social_postActivation.html",
// 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>

View file

@ -0,0 +1,11 @@
<html>
<head>
<title>Activation iframe test</title>
</head>
<body>
<iframe src="social_activate_basic.html"/>
</body>
</html>

View file

@ -0,0 +1,31 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
var Cu = Components.utils;
// Ideally we would use CrashTestUtils.jsm, but that's only available for
// xpcshell tests - so we just copy a ctypes crasher from it.
Cu.import("resource://gre/modules/ctypes.jsm");
var crash = function() { // this will crash when called.
let zero = new ctypes.intptr_t(8);
let badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));
badptr.contents
};
var TestHelper = {
init: function() {
addMessageListener("social-test:crash", this);
},
receiveMessage: function(msg) {
switch (msg.name) {
case "social-test:crash":
privateNoteIntentionalCrash();
crash();
break;
}
},
}
TestHelper.init();

View file

@ -0,0 +1,12 @@
<html>
<head>
<meta charset="utf-8">
<title>Post-Activation test</title>
</head>
<body>
Post Activation landing page
</body>
</html>