mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Backed out changeset e9e43e8256e1 (bug 1287827) for breaking tests
This commit is contained in:
parent
9b96b9599c
commit
b5f9f1309f
@ -1477,4 +1477,4 @@ pref("print.use_simplify_page", true);
|
||||
|
||||
// Space separated list of URLS that are allowed to send objects (instead of
|
||||
// only strings) through webchannels. This list is duplicated in mobile/android/app/mobile.js
|
||||
pref("webchannel.allowObject.urlWhitelist", "https://accounts.firefox.com https://content.cdn.mozilla.net https://input.mozilla.org https://support.mozilla.org https://install.mozilla.org");
|
||||
pref("webchannel.allowObject.urlWhitelist", "https://accounts.firefox.com https://content.cdn.mozilla.net https://hello.firefox.com https://input.mozilla.org https://support.mozilla.org https://install.mozilla.org");
|
||||
|
@ -295,6 +295,18 @@
|
||||
noautofocus="true"
|
||||
position="topcenter topright"/>
|
||||
|
||||
<panel id="loop-notification-panel"
|
||||
class="loop-panel social-panel"
|
||||
type="arrow"
|
||||
hidden="true"
|
||||
noautofocus="true"/>
|
||||
|
||||
<panel id="loop-panel"
|
||||
class="loop-panel social-panel"
|
||||
type="arrow"
|
||||
orient="horizontal"
|
||||
hidden="true"/>
|
||||
|
||||
<menupopup id="toolbar-context-menu"
|
||||
onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('viewToolbarsMenuSeparator'));">
|
||||
<menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
|
||||
|
@ -20,6 +20,16 @@ let whitelist = [
|
||||
// Tracked in bug 1004428.
|
||||
{sourceName: /aboutaccounts\/(main|normalize)\.css$/i,
|
||||
isFromDevTools: false},
|
||||
// TokBox SDK assets, see bug 1032469.
|
||||
{sourceName: /loop\/.*sdk-content\/.*\.css$/i,
|
||||
isFromDevTools: false},
|
||||
// Loop standalone client CSS uses placeholder cross browser pseudo-element
|
||||
{sourceName: /loop\/.*\.css$/i,
|
||||
errorMessage: /Unknown pseudo-class.*placeholder/i,
|
||||
isFromDevTools: false},
|
||||
{sourceName: /loop\/.*shared\/css\/common.css$/i,
|
||||
errorMessage: /Unknown property .user-select./i,
|
||||
isFromDevTools: false},
|
||||
// Highlighter CSS uses a UA-only pseudo-class, see bug 985597.
|
||||
{sourceName: /highlighters\.css$/i,
|
||||
errorMessage: /Unknown pseudo-class.*moz-native-anonymous/i,
|
||||
|
@ -6,5 +6,7 @@ support-files =
|
||||
|
||||
[browser_devices_get_user_media.js]
|
||||
skip-if = buildapp == 'mulet' || (os == "linux" && debug) # linux: bug 976544
|
||||
[browser_devices_get_user_media_about_urls.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_devices_get_user_media_anim.js]
|
||||
[browser_devices_get_user_media_in_frame.js]
|
||||
|
@ -0,0 +1,219 @@
|
||||
/* 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/. */
|
||||
|
||||
const PREF_LOOP_CSP = "loop.CSP";
|
||||
|
||||
var gTab;
|
||||
|
||||
// Taken from dom/media/tests/mochitest/head.js
|
||||
function isMacOSX10_6orOlder() {
|
||||
var is106orOlder = false;
|
||||
|
||||
if (navigator.platform.indexOf("Mac") == 0) {
|
||||
var version = Cc["@mozilla.org/system-info;1"]
|
||||
.getService(Ci.nsIPropertyBag2)
|
||||
.getProperty("version");
|
||||
// the next line is correct: Mac OS 10.6 corresponds to Darwin version 10.x !
|
||||
// Mac OS 10.7 is Darwin version 11.x. the |version| string we've got here
|
||||
// is the Darwin version.
|
||||
is106orOlder = (parseFloat(version) < 11.0);
|
||||
}
|
||||
return is106orOlder;
|
||||
}
|
||||
|
||||
// Screensharing is disabled on older platforms (WinXP and Mac 10.6).
|
||||
function isOldPlatform() {
|
||||
const isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1;
|
||||
if (isMacOSX10_6orOlder() || isWinXP) {
|
||||
info(true, "Screensharing disabled for OSX10.6 and WinXP");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Linux prompts aren't working for screensharing.
|
||||
function isLinux() {
|
||||
return navigator.platform.indexOf("Linux") != -1;
|
||||
}
|
||||
|
||||
function loadPage(aUrl) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
gTab.linkedBrowser.addEventListener("load", function onload() {
|
||||
gTab.linkedBrowser.removeEventListener("load", onload, true);
|
||||
|
||||
is(PopupNotifications._currentNotifications.length, 0,
|
||||
"should start the test without any prior popup notification");
|
||||
|
||||
deferred.resolve();
|
||||
}, true);
|
||||
content.location = aUrl;
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
const permissionError = "error: NotAllowedError: The request is not allowed " +
|
||||
"by the user agent or the platform in the current context.";
|
||||
|
||||
var gTests = [
|
||||
|
||||
{
|
||||
desc: "getUserMedia about:loopconversation shouldn't prompt",
|
||||
run: function checkAudioVideoLoop() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
"set": [[PREF_LOOP_CSP, "default-src 'unsafe-inline'"]],
|
||||
});
|
||||
|
||||
yield loadPage("about:loopconversation");
|
||||
|
||||
info("requesting devices");
|
||||
let promise = promiseObserverCalled("recording-device-events");
|
||||
yield promiseRequestDevice(true, true);
|
||||
yield promise;
|
||||
|
||||
// Wait for the devices to actually be captured and running before
|
||||
// proceeding.
|
||||
yield promisePopupNotification("webRTC-sharingDevices");
|
||||
|
||||
is((yield getMediaCaptureState()), "CameraAndMicrophone",
|
||||
"expected camera and microphone to be shared");
|
||||
|
||||
yield closeStream();
|
||||
|
||||
yield SpecialPowers.popPrefEnv();
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "getUserMedia about:loopconversation should prompt for window sharing",
|
||||
run: function checkShareScreenLoop() {
|
||||
if (isOldPlatform() || isLinux()) {
|
||||
return;
|
||||
}
|
||||
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
"set": [[PREF_LOOP_CSP, "default-src 'unsafe-inline'"]],
|
||||
});
|
||||
|
||||
yield loadPage("about:loopconversation");
|
||||
|
||||
info("requesting screen");
|
||||
let promise = promiseObserverCalled("getUserMedia:request");
|
||||
yield promiseRequestDevice(false, true, null, "window");
|
||||
|
||||
// Wait for the devices to actually be captured and running before
|
||||
// proceeding.
|
||||
yield promisePopupNotification("webRTC-shareDevices");
|
||||
|
||||
is((yield getMediaCaptureState()), "none",
|
||||
"expected camera and microphone not to be shared");
|
||||
|
||||
yield promiseMessage(permissionError, () => {
|
||||
PopupNotifications.panel.firstChild.button.click();
|
||||
});
|
||||
|
||||
yield expectObserverCalled("getUserMedia:response:deny");
|
||||
yield expectObserverCalled("recording-window-ended");
|
||||
|
||||
yield SpecialPowers.popPrefEnv();
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "getUserMedia about:evil should prompt",
|
||||
run: function checkAudioVideoNonLoop() {
|
||||
yield loadPage("about:evil");
|
||||
|
||||
let promise = promiseObserverCalled("getUserMedia:request");
|
||||
yield promiseRequestDevice(true, true);
|
||||
yield promise;
|
||||
|
||||
is((yield getMediaCaptureState()), "none",
|
||||
"expected camera and microphone not to be shared");
|
||||
}
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gTab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = gTab;
|
||||
|
||||
gTab.linkedBrowser.messageManager.loadFrameScript(CONTENT_SCRIPT_HELPER, true);
|
||||
|
||||
Task.spawn(function () {
|
||||
yield ContentTask.spawn(gBrowser.selectedBrowser,
|
||||
getRootDirectory(gTestPath) + "get_user_media.html",
|
||||
function* (url) {
|
||||
const Ci = Components.interfaces;
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
/* A fake about module to map get_user_media.html to different about urls. */
|
||||
function fakeLoopAboutModule() {
|
||||
}
|
||||
|
||||
fakeLoopAboutModule.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]),
|
||||
newChannel: function (aURI, aLoadInfo) {
|
||||
let uri = Services.io.newURI(url, null, null);
|
||||
let chan = Services.io.newChannelFromURIWithLoadInfo(uri, aLoadInfo);
|
||||
chan.owner = Services.scriptSecurityManager.getSystemPrincipal();
|
||||
return chan;
|
||||
},
|
||||
getURIFlags: function (aURI) {
|
||||
return Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
Ci.nsIAboutModule.ALLOW_SCRIPT |
|
||||
Ci.nsIAboutModule.URI_CAN_LOAD_IN_CHILD |
|
||||
Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT;
|
||||
}
|
||||
};
|
||||
|
||||
var factory = XPCOMUtils._getFactory(fakeLoopAboutModule);
|
||||
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
let UUIDGenerator = Components.classes["@mozilla.org/uuid-generator;1"]
|
||||
.getService(Ci.nsIUUIDGenerator);
|
||||
registrar.registerFactory(UUIDGenerator.generateUUID(), "",
|
||||
"@mozilla.org/network/protocol/about;1?what=loopconversation",
|
||||
factory);
|
||||
registrar.registerFactory(UUIDGenerator.generateUUID(), "",
|
||||
"@mozilla.org/network/protocol/about;1?what=evil",
|
||||
factory);
|
||||
});
|
||||
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
"set": [[PREF_PERMISSION_FAKE, true],
|
||||
["media.getusermedia.screensharing.enabled", true]],
|
||||
});
|
||||
|
||||
for (let test of gTests) {
|
||||
info(test.desc);
|
||||
yield test.run();
|
||||
|
||||
// Cleanup before the next test
|
||||
expectNoObserverCalled();
|
||||
}
|
||||
|
||||
yield ContentTask.spawn(gBrowser.selectedBrowser, null,
|
||||
function* () {
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
let cid = Cc["@mozilla.org/network/protocol/about;1?what=loopconversation"];
|
||||
registrar.unregisterFactory(cid,
|
||||
registrar.getClassObject(cid, Ci.nsIFactory));
|
||||
cid = Cc["@mozilla.org/network/protocol/about;1?what=evil"];
|
||||
registrar.unregisterFactory(cid,
|
||||
registrar.getClassObject(cid, Ci.nsIFactory));
|
||||
});
|
||||
}).then(finish, ex => {
|
||||
ok(false, "Unexpected Exception: " + ex);
|
||||
finish();
|
||||
});
|
||||
}
|
@ -102,6 +102,22 @@ static RedirEntry kRedirMap[] = {
|
||||
#endif
|
||||
{ "accounts", "chrome://browser/content/aboutaccounts/aboutaccounts.xhtml",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
// Linkable because of indexeddb use (bug 1228118)
|
||||
{ "loopconversation", "chrome://loop/content/panels/conversation.html",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::ALLOW_SCRIPT |
|
||||
nsIAboutModule::HIDE_FROM_ABOUTABOUT |
|
||||
nsIAboutModule::MAKE_LINKABLE |
|
||||
nsIAboutModule::ENABLE_INDEXED_DB },
|
||||
// Linkable because of indexeddb use (bug 1228118)
|
||||
{ "looppanel", "chrome://loop/content/panels/panel.html",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::ALLOW_SCRIPT |
|
||||
nsIAboutModule::HIDE_FROM_ABOUTABOUT |
|
||||
nsIAboutModule::MAKE_LINKABLE |
|
||||
nsIAboutModule::ENABLE_INDEXED_DB,
|
||||
// Shares an IndexedDB origin with about:loopconversation.
|
||||
"loopconversation" },
|
||||
{ "reader", "chrome://global/content/reader/aboutReader.html",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::ALLOW_SCRIPT |
|
||||
|
@ -108,6 +108,8 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "healthreport", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
#endif
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "looppanel", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "loopconversation", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "reader", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
#if defined(XP_WIN)
|
||||
{ NS_IEHISTORYENUMERATOR_CONTRACTID, &kNS_WINIEHISTORYENUMERATOR_CID },
|
||||
|
@ -64,6 +64,7 @@ var kVersion = 6;
|
||||
* version the button is removed in as the value. e.g. "pocket-button": 5
|
||||
*/
|
||||
var ObsoleteBuiltinButtons = {
|
||||
"loop-button": 5,
|
||||
"pocket-button": 6
|
||||
};
|
||||
|
||||
@ -237,6 +238,7 @@ var CustomizableUIInternal = {
|
||||
"bookmarks-menu-button",
|
||||
"downloads-button",
|
||||
"home-button",
|
||||
"loop-button",
|
||||
];
|
||||
|
||||
if (AppConstants.MOZ_DEV_EDITION) {
|
||||
|
@ -242,6 +242,8 @@
|
||||
|
||||
<panelview id="PanelUI-socialapi" flex="1"/>
|
||||
|
||||
<panelview id="PanelUI-loopapi" flex="1"/>
|
||||
|
||||
<panelview id="PanelUI-feeds" flex="1" oncommand="FeedHandler.subscribeToFeed(null, event);">
|
||||
<label value="&feedsMenu2.label;" class="panel-subview-header"/>
|
||||
</panelview>
|
||||
|
@ -153,6 +153,54 @@ this.UITour = {
|
||||
query: "#panic-button",
|
||||
widgetName: "panic-button",
|
||||
}],
|
||||
["loop", {
|
||||
allowAdd: true,
|
||||
query: "#loop-button",
|
||||
widgetName: "loop-button",
|
||||
}],
|
||||
["loop-newRoom", {
|
||||
infoPanelPosition: "leftcenter topright",
|
||||
query: (aDocument) => {
|
||||
let loopUI = aDocument.defaultView.LoopUI;
|
||||
// Use the parentElement full-width container of the button so our arrow
|
||||
// doesn't overlap the panel contents much.
|
||||
return loopUI.browser.contentDocument.querySelector(".new-room-button").parentElement;
|
||||
},
|
||||
}],
|
||||
["loop-roomList", {
|
||||
infoPanelPosition: "leftcenter topright",
|
||||
query: (aDocument) => {
|
||||
let loopUI = aDocument.defaultView.LoopUI;
|
||||
return loopUI.browser.contentDocument.querySelector(".room-list");
|
||||
},
|
||||
}],
|
||||
["loop-selectedRoomButtons", {
|
||||
infoPanelOffsetY: -20,
|
||||
infoPanelPosition: "start_after",
|
||||
query: (aDocument) => {
|
||||
let chatbox = aDocument.querySelector("chatbox[src^='about\:loopconversation'][selected]");
|
||||
|
||||
// Check that the real target actually exists
|
||||
if (!chatbox || !chatbox.contentDocument ||
|
||||
!chatbox.contentDocument.querySelector(".call-action-group")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// But anchor on the <browser> in the chatbox so the panel doesn't jump to undefined
|
||||
// positions when the copy/email buttons disappear e.g. when the feedback form opens or
|
||||
// somebody else joins the room.
|
||||
return chatbox.content;
|
||||
},
|
||||
}],
|
||||
["loop-signInUpLink", {
|
||||
query: (aDocument) => {
|
||||
let loopBrowser = aDocument.defaultView.LoopUI.browser;
|
||||
if (!loopBrowser) {
|
||||
return null;
|
||||
}
|
||||
return loopBrowser.contentDocument.querySelector(".signin-link");
|
||||
},
|
||||
}],
|
||||
["pocket", {
|
||||
allowAdd: true,
|
||||
query: "#pocket-button",
|
||||
@ -847,12 +895,16 @@ this.UITour = {
|
||||
this.hideInfo(aWindow);
|
||||
// Ensure the menu panel is hidden before calling recreatePopup so popup events occur.
|
||||
this.hideMenu(aWindow, "appMenu");
|
||||
this.hideMenu(aWindow, "loop");
|
||||
this.hideMenu(aWindow, "controlCenter");
|
||||
|
||||
// Clean up panel listeners after calling hideMenu above.
|
||||
aWindow.PanelUI.panel.removeEventListener("popuphiding", this.hideAppMenuAnnotations);
|
||||
aWindow.PanelUI.panel.removeEventListener("ViewShowing", this.hideAppMenuAnnotations);
|
||||
aWindow.PanelUI.panel.removeEventListener("popuphidden", this.onPanelHidden);
|
||||
let loopPanel = aWindow.document.getElementById("loop-notification-panel");
|
||||
loopPanel.removeEventListener("popuphidden", this.onPanelHidden);
|
||||
loopPanel.removeEventListener("popuphiding", this.hideLoopPanelAnnotations);
|
||||
let controlCenterPanel = aWindow.gIdentityHandler._identityPopup;
|
||||
controlCenterPanel.removeEventListener("popuphidden", this.onPanelHidden);
|
||||
controlCenterPanel.removeEventListener("popuphiding", this.hideControlCenterAnnotations);
|
||||
@ -1683,6 +1735,31 @@ this.UITour = {
|
||||
popup.addEventListener("popupshown", onPopupShown);
|
||||
}
|
||||
aWindow.document.getElementById("identity-box").click();
|
||||
} else if (aMenuName == "loop") {
|
||||
let toolbarButton = aWindow.LoopUI.toolbarButton;
|
||||
// It's possible to have a node that isn't placed anywhere
|
||||
if (!toolbarButton || !toolbarButton.node ||
|
||||
!CustomizableUI.getPlacementOfWidget(toolbarButton.node.id)) {
|
||||
log.debug("Can't show the Loop menu since the toolbarButton isn't placed");
|
||||
return;
|
||||
}
|
||||
|
||||
let panel = aWindow.document.getElementById("loop-notification-panel");
|
||||
panel.setAttribute("noautohide", true);
|
||||
if (panel.state != "open") {
|
||||
this.recreatePopup(panel);
|
||||
this.clearAvailableTargetsCache();
|
||||
}
|
||||
|
||||
// An event object is expected but we don't want to toggle the panel with a click if the panel
|
||||
// is already open.
|
||||
aWindow.LoopUI.openPanel({ target: toolbarButton.node, }, "rooms").then(() => {
|
||||
if (aOpenCallback) {
|
||||
aOpenCallback();
|
||||
}
|
||||
});
|
||||
panel.addEventListener("popuphidden", this.onPanelHidden);
|
||||
panel.addEventListener("popuphiding", this.hideLoopPanelAnnotations);
|
||||
} else if (aMenuName == "pocket") {
|
||||
this.getTarget(aWindow, "pocket").then(Task.async(function* onPocketTarget(target) {
|
||||
let widgetGroupWrapper = CustomizableUI.getWidget(target.widgetName);
|
||||
@ -1741,6 +1818,9 @@ this.UITour = {
|
||||
} else if (aMenuName == "controlCenter") {
|
||||
let panel = aWindow.gIdentityHandler._identityPopup;
|
||||
panel.hidePopup();
|
||||
} else if (aMenuName == "loop") {
|
||||
let panel = aWindow.document.getElementById("loop-notification-panel");
|
||||
panel.hidePopup();
|
||||
}
|
||||
},
|
||||
|
||||
@ -1773,6 +1853,12 @@ this.UITour = {
|
||||
UITour.hideAnnotationsForPanel(aEvent, UITour.targetIsInAppMenu);
|
||||
},
|
||||
|
||||
hideLoopPanelAnnotations: function(aEvent) {
|
||||
UITour.hideAnnotationsForPanel(aEvent, (aTarget) => {
|
||||
return aTarget.targetName.startsWith("loop-") && aTarget.targetName != "loop-selectedRoomButtons";
|
||||
});
|
||||
},
|
||||
|
||||
hideControlCenterAnnotations(aEvent) {
|
||||
UITour.hideAnnotationsForPanel(aEvent, (aTarget) => {
|
||||
return aTarget.targetName.startsWith("controlCenter-");
|
||||
@ -1845,6 +1931,12 @@ this.UITour = {
|
||||
case "availableTargets":
|
||||
this.getAvailableTargets(aMessageManager, aWindow, aCallbackID);
|
||||
break;
|
||||
case "loop":
|
||||
const FTU_VERSION = 1;
|
||||
this.sendPageCallback(aMessageManager, aCallbackID, {
|
||||
gettingStartedSeen: (Services.prefs.getIntPref("loop.gettingStarted.latestFTUVersion") >= FTU_VERSION),
|
||||
});
|
||||
break;
|
||||
case "search":
|
||||
case "selectedSearchEngine":
|
||||
Services.search.init(rv => {
|
||||
@ -1888,6 +1980,10 @@ this.UITour = {
|
||||
}
|
||||
} catch (e) {}
|
||||
break;
|
||||
case "Loop:ResumeTourOnFirstJoin":
|
||||
// Ignore aValue in this case to avoid accidentally setting it to false.
|
||||
Services.prefs.setBoolPref("loop.gettingStarted.resumeOnFirstJoin", true);
|
||||
break;
|
||||
default:
|
||||
log.error("setConfiguration: Unknown configuration requested: " + aConfiguration);
|
||||
break;
|
||||
|
@ -31,6 +31,9 @@ skip-if = os == "linux" # Linux: Bug 986760, Bug 989101.
|
||||
[browser_UITour_detach_tab.js]
|
||||
[browser_UITour_forceReaderMode.js]
|
||||
[browser_UITour_heartbeat.js]
|
||||
[browser_UITour_loop.js]
|
||||
skip-if = true # Bug 1225832 - New Loop architecture is not compatible with test.
|
||||
[browser_UITour_loop_panel.js]
|
||||
[browser_UITour_modalDialog.js]
|
||||
skip-if = os != "mac" # modal dialog disabling only working on OS X.
|
||||
[browser_UITour_observe.js]
|
||||
|
@ -21,6 +21,7 @@ add_UITour_task(function* test_availableTargets() {
|
||||
"customize",
|
||||
"help",
|
||||
"home",
|
||||
"loop",
|
||||
"devtools",
|
||||
...(hasPocket ? ["pocket"] : []),
|
||||
"privateWindow",
|
||||
@ -49,6 +50,7 @@ add_UITour_task(function* test_availableTargets_changeWidgets() {
|
||||
"backForward",
|
||||
"customize",
|
||||
"help",
|
||||
"loop",
|
||||
"devtools",
|
||||
"home",
|
||||
...(hasPocket ? ["pocket"] : []),
|
||||
@ -84,6 +86,7 @@ add_UITour_task(function* test_availableTargets_exceptionFromGetTarget() {
|
||||
"customize",
|
||||
"help",
|
||||
"home",
|
||||
"loop",
|
||||
"devtools",
|
||||
...(hasPocket ? ["pocket"] : []),
|
||||
"privateWindow",
|
||||
|
414
browser/components/uitour/test/browser_UITour_loop.js
Normal file
414
browser/components/uitour/test/browser_UITour_loop.js
Normal file
@ -0,0 +1,414 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
var gTestTab;
|
||||
var gContentAPI;
|
||||
var gContentWindow;
|
||||
var gMessageHandlers;
|
||||
var loopButton;
|
||||
var fakeRoom;
|
||||
var loopPanel = document.getElementById("loop-notification-panel");
|
||||
|
||||
const { LoopAPI } = Cu.import("chrome://loop/content/modules/MozLoopAPI.jsm", {});
|
||||
const { LoopRooms } = Cu.import("chrome://loop/content/modules/LoopRooms.jsm", {});
|
||||
const { MozLoopServiceInternal } = Cu.import("chrome://loop/content/modules/MozLoopService.jsm", {});
|
||||
|
||||
const FTU_VERSION = 1;
|
||||
|
||||
function test() {
|
||||
UITourTest();
|
||||
}
|
||||
|
||||
function runOffline(fun) {
|
||||
return (done) => {
|
||||
Services.io.offline = true;
|
||||
fun(function onComplete() {
|
||||
Services.io.offline = false;
|
||||
done();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var tests = [
|
||||
taskify(function* test_gettingStartedClicked_linkOpenedWithExpectedParams() {
|
||||
// Set latestFTUVersion to lower number to show FTU panel.
|
||||
Services.prefs.setIntPref("loop.gettingStarted.latestFTUVersion", 0);
|
||||
Services.prefs.setCharPref("loop.gettingStarted.url", "http://example.com");
|
||||
is(loopButton.open, false, "Menu should initially be closed");
|
||||
loopButton.click();
|
||||
|
||||
yield waitForConditionPromise(() => {
|
||||
return loopButton.open;
|
||||
}, "Menu should be visible after showMenu()");
|
||||
|
||||
gContentAPI.registerPageID("hello-tour_OpenPanel_testPage");
|
||||
yield new Promise(resolve => {
|
||||
gContentAPI.ping(() => resolve());
|
||||
});
|
||||
|
||||
let loopDoc = document.getElementById("loop-notification-panel").children[0].contentDocument;
|
||||
yield waitForConditionPromise(() => {
|
||||
return loopDoc.readyState == 'complete';
|
||||
}, "Loop notification panel document should be fully loaded.", 50);
|
||||
let gettingStartedButton = loopDoc.getElementById("fte-button");
|
||||
ok(gettingStartedButton, "Getting Started button should be found");
|
||||
|
||||
let newTabPromise = waitForConditionPromise(() => {
|
||||
return gBrowser.currentURI.path.includes("utm_source=firefox-browser");
|
||||
}, "New tab with utm_content=testPageNewID should have opened");
|
||||
|
||||
gettingStartedButton.click();
|
||||
yield newTabPromise;
|
||||
ok(gBrowser.currentURI.path.includes("utm_content=hello-tour_OpenPanel_testPage"),
|
||||
"Expected URL opened (" + gBrowser.currentURI.path + ")");
|
||||
yield gBrowser.removeCurrentTab();
|
||||
|
||||
checkLoopPanelIsHidden();
|
||||
}),
|
||||
taskify(function* test_gettingStartedClicked_linkOpenedWithExpectedParams2() {
|
||||
// Set latestFTUVersion to lower number to show FTU panel.
|
||||
Services.prefs.setIntPref("loop.gettingStarted.latestFTUVersion", 0);
|
||||
// Force a refresh of the loop panel since going from seen -> unseen doesn't trigger
|
||||
// automatic re-rendering.
|
||||
let loopWin = document.getElementById("loop-notification-panel").children[0].contentWindow;
|
||||
var event = new loopWin.CustomEvent("GettingStartedSeen", { detail: false });
|
||||
loopWin.dispatchEvent(event);
|
||||
|
||||
UITour.pageIDsForSession.clear();
|
||||
Services.prefs.setCharPref("loop.gettingStarted.url", "http://example.com");
|
||||
is(loopButton.open, false, "Menu should initially be closed");
|
||||
loopButton.click();
|
||||
|
||||
yield waitForConditionPromise(() => {
|
||||
return loopButton.open;
|
||||
}, "Menu should be visible after showMenu()");
|
||||
|
||||
|
||||
gContentAPI.registerPageID("hello-tour_OpenPanel_testPageOldId");
|
||||
yield new Promise(resolve => {
|
||||
gContentAPI.ping(() => resolve());
|
||||
});
|
||||
// Set the time of the page ID to 10 hours earlier, so that it is considered "expired".
|
||||
UITour.pageIDsForSession.set("hello-tour_OpenPanel_testPageOldId",
|
||||
{lastSeen: Date.now() - (10 * 60 * 60 * 1000)});
|
||||
|
||||
let loopDoc = loopWin.document;
|
||||
let gettingStartedButton = loopDoc.getElementById("fte-button");
|
||||
ok(gettingStartedButton, "Getting Started button should be found");
|
||||
|
||||
let newTabPromise = waitForConditionPromise(() => {
|
||||
Services.console.logStringMessage(gBrowser.currentURI.path);
|
||||
return gBrowser.currentURI.path.includes("utm_source=firefox-browser");
|
||||
}, "New tab with utm_content=testPageNewID should have opened");
|
||||
|
||||
gettingStartedButton.click();
|
||||
yield newTabPromise;
|
||||
ok(!gBrowser.currentURI.path.includes("utm_content=hello-tour_OpenPanel_testPageOldId"),
|
||||
"Expected URL opened without the utm_content parameter (" +
|
||||
gBrowser.currentURI.path + ")");
|
||||
yield gBrowser.removeCurrentTab();
|
||||
|
||||
checkLoopPanelIsHidden();
|
||||
}),
|
||||
// Test the menu was cleaned up in teardown.
|
||||
taskify(function* setup_menu_cleanup() {
|
||||
gContentAPI.showMenu("loop");
|
||||
|
||||
yield waitForConditionPromise(() => {
|
||||
return loopButton.open;
|
||||
}, "Menu should be visible after showMenu()");
|
||||
|
||||
// Leave it open so it gets torn down and we can test below that teardown was succesful.
|
||||
}),
|
||||
taskify(function* test_menu_cleanup() {
|
||||
// Test that the open menu from above was torn down fully.
|
||||
checkLoopPanelIsHidden();
|
||||
}),
|
||||
function test_availableTargets(done) {
|
||||
gContentAPI.showMenu("loop");
|
||||
gContentAPI.getConfiguration("availableTargets", (data) => {
|
||||
for (let targetName of ["loop-newRoom", "loop-roomList", "loop-signInUpLink"]) {
|
||||
isnot(data.targets.indexOf(targetName), -1, targetName + " should exist");
|
||||
}
|
||||
done();
|
||||
});
|
||||
},
|
||||
function test_getConfigurationLoop(done) {
|
||||
let gettingStartedSeen = Services.prefs.getIntPref("loop.gettingStarted.latestFTUVersion") >= FTU_VERSION;
|
||||
gContentAPI.getConfiguration("loop", (data) => {
|
||||
is(data.gettingStartedSeen, gettingStartedSeen,
|
||||
"The configuration property should equal that of the pref");
|
||||
done();
|
||||
});
|
||||
},
|
||||
function test_hideMenuHidesAnnotations(done) {
|
||||
let infoPanel = document.getElementById("UITourTooltip");
|
||||
let highlightPanel = document.getElementById("UITourHighlightContainer");
|
||||
|
||||
gContentAPI.showMenu("loop", function menuCallback() {
|
||||
gContentAPI.showHighlight("loop-roomList");
|
||||
gContentAPI.showInfo("loop-newRoom", "Make a new room", "AKA. conversation");
|
||||
UITour.getTarget(window, "loop-newRoom").then((target) => {
|
||||
waitForPopupAtAnchor(infoPanel, target.node, Task.async(function* checkPanelIsOpen() {
|
||||
isnot(loopPanel.state, "closed", "Loop panel should still be open");
|
||||
ok(loopPanel.hasAttribute("noautohide"), "@noautohide should still be on the loop panel");
|
||||
is(highlightPanel.getAttribute("targetName"), "loop-roomList", "Check highlight @targetname");
|
||||
is(infoPanel.getAttribute("targetName"), "loop-newRoom", "Check info panel @targetname");
|
||||
|
||||
info("Close the loop menu and make sure the annotations inside disappear");
|
||||
let hiddenPromises = [promisePanelElementHidden(window, infoPanel),
|
||||
promisePanelElementHidden(window, highlightPanel)];
|
||||
gContentAPI.hideMenu("loop");
|
||||
yield Promise.all(hiddenPromises);
|
||||
isnot(infoPanel.state, "open", "Info panel should have automatically hid");
|
||||
isnot(highlightPanel.state, "open", "Highlight panel should have automatically hid");
|
||||
done();
|
||||
}), "Info panel should be anchored to the new room button");
|
||||
});
|
||||
});
|
||||
},
|
||||
runOffline(function test_notifyLoopChatWindowOpenedClosed(done) {
|
||||
gContentAPI.observe((event, params) => {
|
||||
is(event, "Loop:ChatWindowOpened", "Check Loop:ChatWindowOpened notification");
|
||||
gContentAPI.observe((event, params) => {
|
||||
is(event, "Loop:ChatWindowShown", "Check Loop:ChatWindowShown notification");
|
||||
gContentAPI.observe((event, params) => {
|
||||
is(event, "Loop:ChatWindowClosed", "Check Loop:ChatWindowClosed notification");
|
||||
gContentAPI.observe((event, params) => {
|
||||
ok(false, "No more notifications should have arrived");
|
||||
});
|
||||
});
|
||||
done();
|
||||
});
|
||||
document.querySelector("#pinnedchats > chatbox").close();
|
||||
});
|
||||
LoopRooms.open("fakeTourRoom");
|
||||
}),
|
||||
runOffline(function test_notifyLoopRoomURLCopied(done) {
|
||||
gContentAPI.observe((event, params) => {
|
||||
is(event, "Loop:ChatWindowOpened", "Loop chat window should've opened");
|
||||
gContentAPI.observe((event, params) => {
|
||||
is(event, "Loop:ChatWindowShown", "Check Loop:ChatWindowShown notification");
|
||||
|
||||
let chat = document.querySelector("#pinnedchats > chatbox");
|
||||
gContentAPI.observe((event, params) => {
|
||||
is(event, "Loop:RoomURLCopied", "Check Loop:RoomURLCopied notification");
|
||||
gContentAPI.observe((event, params) => {
|
||||
is(event, "Loop:ChatWindowClosed", "Check Loop:ChatWindowClosed notification");
|
||||
});
|
||||
chat.close();
|
||||
done();
|
||||
});
|
||||
|
||||
let window = chat.content.contentWindow;
|
||||
waitForConditionPromise(
|
||||
() => chat.content.contentDocument.querySelector(".btn-copy"),
|
||||
"Copy button should be there"
|
||||
).then(() => chat.content.contentDocument.querySelector(".btn-copy").click());
|
||||
});
|
||||
});
|
||||
LoopRooms.open("fakeTourRoom");
|
||||
}),
|
||||
runOffline(function test_notifyLoopRoomURLEmailed(done) {
|
||||
gContentAPI.observe((event, params) => {
|
||||
is(event, "Loop:ChatWindowOpened", "Loop chat window should've opened");
|
||||
gContentAPI.observe((event, params) => {
|
||||
is(event, "Loop:ChatWindowShown", "Check Loop:ChatWindowShown notification");
|
||||
|
||||
let chat = document.querySelector("#pinnedchats > chatbox");
|
||||
let composeEmailCalled = false;
|
||||
|
||||
gContentAPI.observe((event, params) => {
|
||||
is(event, "Loop:RoomURLEmailed", "Check Loop:RoomURLEmailed notification");
|
||||
ok(composeEmailCalled, "mozLoop.composeEmail should be called");
|
||||
gContentAPI.observe((event, params) => {
|
||||
is(event, "Loop:ChatWindowClosed", "Check Loop:ChatWindowClosed notification");
|
||||
});
|
||||
chat.close();
|
||||
done();
|
||||
});
|
||||
|
||||
gMessageHandlers.ComposeEmail = function(message, reply) {
|
||||
let [subject, body, recipient] = message.data;
|
||||
ok(subject, "composeEmail should be invoked with at least a subject value");
|
||||
composeEmailCalled = true;
|
||||
reply();
|
||||
};
|
||||
|
||||
waitForConditionPromise(
|
||||
() => chat.content.contentDocument.querySelector(".btn-email"),
|
||||
"Email button should be there"
|
||||
).then(() => chat.content.contentDocument.querySelector(".btn-email").click());
|
||||
});
|
||||
});
|
||||
LoopRooms.open("fakeTourRoom");
|
||||
}),
|
||||
taskify(function* test_arrow_panel_position() {
|
||||
is(loopButton.open, false, "Menu should initially be closed");
|
||||
let popup = document.getElementById("UITourTooltip");
|
||||
|
||||
yield showMenuPromise("loop");
|
||||
|
||||
let currentTarget = "loop-newRoom";
|
||||
yield showInfoPromise(currentTarget, "This is " + currentTarget, "My arrow should be on the side");
|
||||
is(popup.popupBoxObject.alignmentPosition, "start_before", "Check " + currentTarget + " position");
|
||||
|
||||
currentTarget = "loop-roomList";
|
||||
yield showInfoPromise(currentTarget, "This is " + currentTarget, "My arrow should be on the side");
|
||||
is(popup.popupBoxObject.alignmentPosition, "start_before", "Check " + currentTarget + " position");
|
||||
|
||||
currentTarget = "loop-signInUpLink";
|
||||
yield showInfoPromise(currentTarget, "This is " + currentTarget, "My arrow should be underneath");
|
||||
is(popup.popupBoxObject.alignmentPosition, "after_end", "Check " + currentTarget + " position");
|
||||
}),
|
||||
taskify(function* test_setConfiguration() {
|
||||
is(Services.prefs.getBoolPref("loop.gettingStarted.resumeOnFirstJoin"), false, "pref should be false but exist");
|
||||
gContentAPI.setConfiguration("Loop:ResumeTourOnFirstJoin", true);
|
||||
|
||||
yield waitForConditionPromise(() => {
|
||||
return Services.prefs.getBoolPref("loop.gettingStarted.resumeOnFirstJoin");
|
||||
}, "Pref should change to true via setConfiguration");
|
||||
|
||||
Services.prefs.clearUserPref("loop.gettingStarted.resumeOnFirstJoin");
|
||||
}),
|
||||
taskify(function* test_resumeViaMenuPanel_roomClosedTabOpen() {
|
||||
Services.prefs.setBoolPref("loop.gettingStarted.resumeOnFirstJoin", true);
|
||||
|
||||
// Create a fake room and then add a fake non-owner participant
|
||||
let roomsMap = setupFakeRoom();
|
||||
roomsMap.get("fakeTourRoom").participants = [{
|
||||
owner: false,
|
||||
}];
|
||||
|
||||
// Set the tour URL to be the current page with a different query param
|
||||
let gettingStartedURL = gTestTab.linkedBrowser.currentURI.resolve("?gettingstarted=1");
|
||||
Services.prefs.setCharPref("loop.gettingStarted.url", gettingStartedURL);
|
||||
|
||||
let observationPromise = new Promise((resolve) => {
|
||||
gContentAPI.observe((event, params) => {
|
||||
is(event, "Loop:IncomingConversation", "Page should have been notified about incoming conversation");
|
||||
is(params.conversationOpen, false, "conversationOpen should be false");
|
||||
is(gBrowser.selectedTab, gTestTab, "The same tab should be selected");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
// Now open the menu while that non-owner is in the fake room to trigger resuming the tour
|
||||
yield showMenuPromise("loop");
|
||||
|
||||
yield observationPromise;
|
||||
Services.prefs.clearUserPref("loop.gettingStarted.resumeOnFirstJoin");
|
||||
}),
|
||||
taskify(function* test_resumeViaMenuPanel_roomClosedTabClosed() {
|
||||
Services.prefs.setBoolPref("loop.gettingStarted.resumeOnFirstJoin", true);
|
||||
|
||||
// Create a fake room and then add a fake non-owner participant
|
||||
let roomsMap = setupFakeRoom();
|
||||
roomsMap.get("fakeTourRoom").participants = [{
|
||||
owner: false,
|
||||
}];
|
||||
|
||||
// Set the tour URL to a page that's not open yet
|
||||
Services.prefs.setCharPref("loop.gettingStarted.url", gBrowser.currentURI.prePath);
|
||||
|
||||
let newTabPromise = waitForConditionPromise(() => {
|
||||
return gBrowser.currentURI.path.includes("incomingConversation=waiting");
|
||||
}, "New tab with incomingConversation=waiting should have opened");
|
||||
|
||||
// Now open the menu while that non-owner is in the fake room to trigger resuming the tour
|
||||
yield showMenuPromise("loop");
|
||||
|
||||
yield newTabPromise;
|
||||
|
||||
yield gBrowser.removeCurrentTab();
|
||||
Services.prefs.clearUserPref("loop.gettingStarted.resumeOnFirstJoin");
|
||||
}),
|
||||
];
|
||||
|
||||
// End tests
|
||||
|
||||
function checkLoopPanelIsHidden() {
|
||||
ok(!loopPanel.hasAttribute("noautohide"), "@noautohide on the loop panel should have been cleaned up");
|
||||
ok(!loopPanel.hasAttribute("panelopen"), "The panel shouldn't have @panelopen");
|
||||
isnot(loopPanel.state, "open", "The panel shouldn't be open");
|
||||
is(loopButton.hasAttribute("open"), false, "Loop button should know that the panel is closed");
|
||||
}
|
||||
|
||||
function setupFakeRoom() {
|
||||
let room = Object.create(fakeRoom);
|
||||
let roomsMap = new Map([
|
||||
[room.roomToken, room]
|
||||
]);
|
||||
LoopRooms.stubCache(roomsMap);
|
||||
return roomsMap;
|
||||
}
|
||||
|
||||
if (Services.prefs.getBoolPref("loop.enabled")) {
|
||||
loopButton = window.LoopUI.toolbarButton.node;
|
||||
|
||||
fakeRoom = {
|
||||
decryptedContext: { roomName: "fakeTourRoom" },
|
||||
participants: [],
|
||||
maxSize: 2,
|
||||
ctime: Date.now()
|
||||
};
|
||||
for (let prop of ["roomToken", "roomOwner", "roomUrl"])
|
||||
fakeRoom[prop] = "fakeTourRoom";
|
||||
|
||||
LoopAPI.stubMessageHandlers(gMessageHandlers = {
|
||||
// Stub the rooms object API to fully control the test behavior.
|
||||
"Rooms:*": function(action, message, reply) {
|
||||
switch (action.split(":").pop()) {
|
||||
case "GetAll":
|
||||
reply([fakeRoom]);
|
||||
break;
|
||||
case "Get":
|
||||
reply(fakeRoom);
|
||||
break;
|
||||
case "Join":
|
||||
reply({
|
||||
apiKey: "fakeTourRoom",
|
||||
sessionToken: "fakeTourRoom",
|
||||
sessionId: "fakeTourRoom",
|
||||
expires: Date.now() + 240000
|
||||
});
|
||||
break;
|
||||
case "RefreshMembership":
|
||||
reply({ expires: Date.now() + 240000 });
|
||||
default:
|
||||
reply();
|
||||
}
|
||||
},
|
||||
// Stub the metadata retrieval to suppress console warnings and return faster.
|
||||
GetSelectedTabMetadata: function(message, reply) {
|
||||
reply({ favicon: null });
|
||||
}
|
||||
});
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("loop.gettingStarted.resumeOnFirstJoin");
|
||||
Services.prefs.clearUserPref("loop.gettingStarted.latestFTUVersion");
|
||||
Services.prefs.clearUserPref("loop.gettingStarted.url");
|
||||
Services.io.offline = false;
|
||||
|
||||
// Copied from browser/components/loop/test/mochitest/head.js
|
||||
// Remove the iframe after each test. This also avoids mochitest complaining
|
||||
// about leaks on shutdown as we intentionally hold the iframe open for the
|
||||
// life of the application.
|
||||
let frameId = loopButton.getAttribute("notificationFrameId");
|
||||
let frame = document.getElementById(frameId);
|
||||
if (frame) {
|
||||
frame.remove();
|
||||
}
|
||||
|
||||
// Remove the stubbed rooms.
|
||||
LoopRooms.stubCache(null);
|
||||
// Restore the stubbed handlers.
|
||||
LoopAPI.restore();
|
||||
});
|
||||
} else {
|
||||
ok(true, "Loop is disabled so skip the UITour Loop tests");
|
||||
tests = [];
|
||||
}
|
67
browser/components/uitour/test/browser_UITour_loop_panel.js
Normal file
67
browser/components/uitour/test/browser_UITour_loop_panel.js
Normal file
@ -0,0 +1,67 @@
|
||||
"use strict";
|
||||
|
||||
var gTestTab;
|
||||
var gContentAPI;
|
||||
var gContentWindow;
|
||||
var gMessageHandlers;
|
||||
var loopButton;
|
||||
var fakeRoom;
|
||||
var loopPanel = document.getElementById("loop-notification-panel");
|
||||
|
||||
const { LoopAPI } = Cu.import("chrome://loop/content/modules/MozLoopAPI.jsm", {});
|
||||
const { LoopRooms } = Cu.import("chrome://loop/content/modules/LoopRooms.jsm", {});
|
||||
|
||||
if (!Services.prefs.getBoolPref("loop.enabled")) {
|
||||
ok(true, "Loop is disabled so skip the UITour Loop tests");
|
||||
} else {
|
||||
function checkLoopPanelIsHidden() {
|
||||
ok(!loopPanel.hasAttribute("noautohide"), "@noautohide on the loop panel should have been cleaned up");
|
||||
ok(!loopPanel.hasAttribute("panelopen"), "The panel shouldn't have @panelopen");
|
||||
isnot(loopPanel.state, "open", "The panel shouldn't be open");
|
||||
is(loopButton.hasAttribute("open"), false, "Loop button should know that the panel is closed");
|
||||
}
|
||||
|
||||
add_task(setup_UITourTest);
|
||||
|
||||
add_task(function() {
|
||||
loopButton = window.LoopUI.toolbarButton.node;
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("loop.gettingStarted.latestFTUVersion");
|
||||
Services.io.offline = false;
|
||||
|
||||
// Copied from browser/components/loop/test/mochitest/head.js
|
||||
// Remove the iframe after each test. This also avoids mochitest complaining
|
||||
// about leaks on shutdown as we intentionally hold the iframe open for the
|
||||
// life of the application.
|
||||
let frameId = loopButton.getAttribute("notificationFrameId");
|
||||
let frame = document.getElementById(frameId);
|
||||
if (frame) {
|
||||
frame.remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
add_UITour_task(function* test_menu_show_hide() {
|
||||
// The targets to highlight only appear after getting started is launched.
|
||||
// Set latestFTUVersion to lower number to show FTU panel.
|
||||
Services.prefs.setIntPref("loop.gettingStarted.latestFTUVersion", 0);
|
||||
is(loopButton.open, false, "Menu should initially be closed");
|
||||
gContentAPI.showMenu("loop");
|
||||
|
||||
yield waitForConditionPromise(() => {
|
||||
return loopPanel.state == "open";
|
||||
}, "Menu should be visible after showMenu()");
|
||||
|
||||
ok(loopPanel.hasAttribute("noautohide"), "@noautohide should be on the loop panel");
|
||||
ok(loopPanel.hasAttribute("panelopen"), "The panel should have @panelopen");
|
||||
ok(loopButton.hasAttribute("open"), "Loop button should know that the menu is open");
|
||||
|
||||
gContentAPI.hideMenu("loop");
|
||||
yield waitForConditionPromise(() => {
|
||||
return !loopButton.open;
|
||||
}, "Menu should be hidden after hideMenu()");
|
||||
|
||||
checkLoopPanelIsHidden();
|
||||
});
|
||||
}
|
@ -99,6 +99,19 @@ quit-button.tooltiptext.linux2 = Quit %1$S (%2$S)
|
||||
# %2$S is the keyboard shortcut
|
||||
quit-button.tooltiptext.mac = Quit %1$S (%2$S)
|
||||
|
||||
# LOCALIZATION NOTE(loop-call-button3.label): This is a brand name, request
|
||||
# approval before you change it.
|
||||
loop-call-button3.label = Hello
|
||||
loop-call-button3.tooltiptext2 = Browse this page with a friend
|
||||
loop-call-button3-error.tooltiptext = Error!
|
||||
loop-call-button3-donotdisturb.tooltiptext = Do not disturb
|
||||
loop-call-button3-screensharing.tooltiptext = You are sharing your screen
|
||||
loop-call-button3-active.tooltiptext2 = You are sharing your tabs
|
||||
loop-call-button3-participantswaiting.tooltiptext2 = Someone is waiting for you
|
||||
# LOCALIZATION NOTE(loop-call-button3-pb.tooltiptext): Shown when the button is
|
||||
# placed inside a Private Browsing window. %S is the value of loop-call-button3.label.
|
||||
loop-call-button3-pb.tooltiptext = %S is not available in Private Browsing
|
||||
|
||||
social-share-button.label = Share This Page
|
||||
social-share-button.tooltiptext = Share this page
|
||||
|
||||
|
@ -0,0 +1,9 @@
|
||||
# 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/.
|
||||
|
||||
# Panel Strings
|
||||
|
||||
## LOCALIZATION NOTE(clientShortname2): This should not be localized and
|
||||
## should remain "Firefox Hello" for all locales.
|
||||
clientShortname2=Firefox Hello
|
@ -27,6 +27,7 @@
|
||||
locale/browser/browser.properties (%chrome/browser/browser.properties)
|
||||
locale/browser/customizableui/customizableWidgets.properties (%chrome/browser/customizableui/customizableWidgets.properties)
|
||||
locale/browser/lightweightThemes.properties (%chrome/browser/lightweightThemes.properties)
|
||||
locale/browser/loop/loop.properties (%chrome/browser/loop/loop.properties)
|
||||
locale/browser/newTab.dtd (%chrome/browser/newTab.dtd)
|
||||
locale/browser/newTab.properties (%chrome/browser/newTab.properties)
|
||||
locale/browser/pageInfo.dtd (%chrome/browser/pageInfo.dtd)
|
||||
|
@ -81,6 +81,11 @@ var PanelFrameInternal = {
|
||||
attrs["message"] = "true";
|
||||
attrs["messagemanagergroup"] = aType;
|
||||
}
|
||||
if (aType == "loop") {
|
||||
attrs.message = true;
|
||||
attrs.messagemanagergroup = "social";
|
||||
attrs.autocompletepopup = "PopupAutoComplete";
|
||||
}
|
||||
for (let [k, v] of Iterator(attrs)) {
|
||||
frame.setAttribute(k, v);
|
||||
}
|
||||
|
@ -270,8 +270,15 @@ function getHost(uri, href) {
|
||||
} catch (ex) {}
|
||||
if (!host) {
|
||||
if (uri && uri.scheme.toLowerCase() == "about") {
|
||||
// For about URIs, just use the full spec, without any #hash parts.
|
||||
host = uri.specIgnoringRef;
|
||||
// Special case-ing Loop/ Hello gUM requests.
|
||||
if (uri.specIgnoringRef == "about:loopconversation") {
|
||||
const kBundleURI = "chrome://browser/locale/loop/loop.properties";
|
||||
let bundle = Services.strings.createBundle(kBundleURI);
|
||||
host = bundle.GetStringFromName("clientShortname2");
|
||||
} else {
|
||||
// For other about URIs, just use the full spec, without any #hash parts.
|
||||
host = uri.specIgnoringRef;
|
||||
}
|
||||
} else {
|
||||
// This is unfortunate, but we should display *something*...
|
||||
const kBundleURI = "chrome://browser/locale/browser.properties";
|
||||
|
@ -923,4 +923,4 @@ pref("dom.audiochannel.mediaControl", true);
|
||||
|
||||
// Space separated list of URLS that are allowed to send objects (instead of
|
||||
// only strings) through webchannels. This list is duplicated in browser/app/profile/firefox.js
|
||||
pref("webchannel.allowObject.urlWhitelist", "https://accounts.firefox.com https://content.cdn.mozilla.net https://input.mozilla.org https://support.mozilla.org https://install.mozilla.org");
|
||||
pref("webchannel.allowObject.urlWhitelist", "https://accounts.firefox.com https://content.cdn.mozilla.net https://hello.firefox.com https://input.mozilla.org https://support.mozilla.org https://install.mozilla.org");
|
||||
|
@ -287,6 +287,13 @@ user_pref("dom.apps.customization.enabled", true);
|
||||
user_pref("browser.newtabpage.directory.source", 'data:application/json,{"testing":1}');
|
||||
user_pref("browser.newtabpage.directory.ping", "");
|
||||
|
||||
// Enable Loop
|
||||
user_pref("loop.debug.loglevel", "All");
|
||||
user_pref("loop.enabled", true);
|
||||
user_pref("loop.throttled", false);
|
||||
user_pref("loop.server", "http://%(server)s/browser/browser/extensions/loop/chrome/test/mochitest/loop_fxa.sjs?");
|
||||
user_pref("loop.CSP","default-src 'self' about: file: chrome: data: wss://* http://* https://*");
|
||||
|
||||
// Ensure UITour won't hit the network
|
||||
user_pref("browser.uitour.pinnedTabUrl", "http://%(server)s/uitour-dummy/pinnedTab");
|
||||
user_pref("browser.uitour.url", "http://%(server)s/uitour-dummy/tour");
|
||||
|
Loading…
Reference in New Issue
Block a user