mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to inbound. a=merge
CLOSED TREE
This commit is contained in:
commit
f87c951071
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="759a1f935a6a81c32ad66e39a6353b334dfa4f91"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
@ -134,7 +134,7 @@
|
||||
<project name="platform/hardware/akm" path="hardware/akm" revision="6d3be412647b0eab0adff8a2768736cf4eb68039"/>
|
||||
<project groups="invensense" name="platform/hardware/invensense" path="hardware/invensense" revision="e6d9ab28b4f4e7684f6c07874ee819c9ea0002a2"/>
|
||||
<project name="platform/hardware/ril" path="hardware/ril" revision="865ce3b4a2ba0b3a31421ca671f4d6c5595f8690"/>
|
||||
<project name="kernel/common" path="kernel" revision="0be9cc12cd81b145e1471016c19722429ff9285e"/>
|
||||
<project name="kernel/common" path="kernel" revision="a2977758950865feb5980996d8e889677dea3bd4"/>
|
||||
<project name="platform/system/core" path="system/core" revision="7992618bd4ee33ce96897675a5c0a9b619122f13"/>
|
||||
<project name="u-boot" path="u-boot" revision="f1502910977ac88f43da7bf9277c3523ad4b0b2f"/>
|
||||
<project name="vendor/sprd/gps" path="vendor/sprd/gps" revision="7d6e1269be7186b2073fa568958b357826692c4b"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="759a1f935a6a81c32ad66e39a6353b334dfa4f91"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="759a1f935a6a81c32ad66e39a6353b334dfa4f91"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="759a1f935a6a81c32ad66e39a6353b334dfa4f91"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="759a1f935a6a81c32ad66e39a6353b334dfa4f91"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="759a1f935a6a81c32ad66e39a6353b334dfa4f91"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="759a1f935a6a81c32ad66e39a6353b334dfa4f91"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
@ -125,7 +125,7 @@
|
||||
<!-- Flame specific things -->
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="1bb28abbc215f45220620af5cd60a8ac1be93722"/>
|
||||
<project name="device/qcom/common" path="device/qcom/common" revision="2501e5940ba69ece7654ff85611c76ae5bda299c"/>
|
||||
<project name="device-flame" path="device/t2m/flame" remote="b2g" revision="b83fc73de7b64594cd74b33e498bf08332b5d87b"/>
|
||||
<project name="device-flame" path="device/t2m/flame" remote="b2g" revision="a9f3f8fb8b0844724de32426b7bcc4e6dc4fa2ed"/>
|
||||
<project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="0865bc4134b67220df4058625fba29305d6b10c3"/>
|
||||
<project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="fda40423ffa573dc6cafd3780515010cb2a086be"/>
|
||||
<project name="platform_bootable_recovery" path="bootable/recovery" remote="b2g" revision="d5e53ed6f22fa06052351dc03510af9473af01ea"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="759a1f935a6a81c32ad66e39a6353b334dfa4f91"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"git_revision": "759a1f935a6a81c32ad66e39a6353b334dfa4f91",
|
||||
"git_revision": "8e64346ce8197b50b815a294278797bc144aa3e6",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "d88d79f407d14635451063c4397724d836efcbaa",
|
||||
"revision": "1bbaa54b674c42e0d8b2fe31d8b0080901811fa0",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="759a1f935a6a81c32ad66e39a6353b334dfa4f91"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="759a1f935a6a81c32ad66e39a6353b334dfa4f91"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -1327,8 +1327,8 @@ pref("services.sync.prefs.sync.xpinstall.whitelist.required", true);
|
||||
|
||||
// Developer edition preferences
|
||||
#ifdef MOZ_DEV_EDITION
|
||||
pref("lightweightThemes.selectedThemeID", "firefox-devedition@mozilla.org");
|
||||
pref("browser.devedition.theme.enabled", true);
|
||||
sticky_pref("lightweightThemes.selectedThemeID", "firefox-devedition@mozilla.org");
|
||||
sticky_pref("browser.devedition.theme.enabled", true);
|
||||
#endif
|
||||
|
||||
// Developer edition promo preferences
|
||||
@ -1443,6 +1443,15 @@ pref("devtools.performance.ui.show-idle-blocks", true);
|
||||
pref("devtools.performance.ui.enable-memory", false);
|
||||
pref("devtools.performance.ui.enable-framerate", true);
|
||||
pref("devtools.performance.ui.show-jit-optimizations", false);
|
||||
// If in aurora (40.0, will revert for 40.1), set default
|
||||
// to retro mode.
|
||||
// TODO bug 1160313
|
||||
#if MOZ_UPDATE_CHANNEL == aurora
|
||||
pref("devtools.performance.ui.retro-mode", true);
|
||||
#else
|
||||
pref("devtools.performance.ui.retro-mode", false);
|
||||
#endif
|
||||
|
||||
|
||||
// The default cache UI setting
|
||||
pref("devtools.cache.disabled", false);
|
||||
@ -1507,9 +1516,9 @@ pref("devtools.webaudioeditor.inspectorWidth", 300);
|
||||
|
||||
// Default theme ("dark" or "light")
|
||||
#ifdef MOZ_DEV_EDITION
|
||||
pref("devtools.theme", "dark");
|
||||
sticky_pref("devtools.theme", "dark");
|
||||
#else
|
||||
pref("devtools.theme", "light");
|
||||
sticky_pref("devtools.theme", "light");
|
||||
#endif
|
||||
|
||||
// Display the introductory text
|
||||
@ -1646,10 +1655,10 @@ pref("browser.newtabpage.rows", 3);
|
||||
pref("browser.newtabpage.columns", 5);
|
||||
|
||||
// directory tiles download URL
|
||||
pref("browser.newtabpage.directory.source", "https://tiles.services.mozilla.com/v2/links/fetch/%LOCALE%");
|
||||
pref("browser.newtabpage.directory.source", "https://tiles.services.mozilla.com/v3/links/fetch/%LOCALE%/%CHANNEL%");
|
||||
|
||||
// endpoint to send newtab click and view pings
|
||||
pref("browser.newtabpage.directory.ping", "https://tiles.services.mozilla.com/v2/links/");
|
||||
pref("browser.newtabpage.directory.ping", "https://tiles.services.mozilla.com/v3/links/");
|
||||
|
||||
// Enable the DOM fullscreen API.
|
||||
pref("full-screen-api.enabled", true);
|
||||
@ -1863,7 +1872,7 @@ pref("browser.polaris.enabled", false);
|
||||
pref("privacy.trackingprotection.ui.enabled", false);
|
||||
#endif
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
#ifdef E10S_TESTING_ONLY
|
||||
// At the moment, autostart.2 is used, while autostart.1 is unused.
|
||||
// We leave it here set to false to reset users' defaults and allow
|
||||
// us to change everybody to true in the future, when desired.
|
||||
@ -1871,7 +1880,7 @@ pref("browser.tabs.remote.autostart.1", false);
|
||||
pref("browser.tabs.remote.autostart.2", true);
|
||||
#endif
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
#ifdef E10S_TESTING_ONLY
|
||||
// Enable e10s add-on interposition by default.
|
||||
pref("extensions.interposition.enabled", true);
|
||||
pref("extensions.interposition.prefetching", true);
|
||||
@ -1900,6 +1909,7 @@ pref("browser.readinglist.sidebarEverOpened", false);
|
||||
pref("readinglist.scheduler.enabled", false);
|
||||
pref("readinglist.server", "https://readinglist.services.mozilla.com/v1");
|
||||
|
||||
pref("browser.reader.detectedFirstArticle", false);
|
||||
// Don't limit how many nodes we care about on desktop:
|
||||
pref("reader.parse-node-limit", 0);
|
||||
|
||||
|
@ -133,7 +133,7 @@ Site.prototype = {
|
||||
|
||||
if (this.link.targetedSite) {
|
||||
this.node.setAttribute("suggested", true);
|
||||
let targetedSite = `<strong> ${this.link.targetedSite} </strong>`;
|
||||
let targetedSite = `<strong> ${this.link.targetedName} </strong>`;
|
||||
this._querySelector(".newtab-suggested").innerHTML =
|
||||
`<div class='newtab-suggested-bounds'> ${newTabString("suggested.button", [targetedSite])} </div>`;
|
||||
}
|
||||
|
@ -555,7 +555,9 @@ addEventListener("unload", () => {
|
||||
}, false);
|
||||
|
||||
addMessageListener("Browser:AppTab", function(message) {
|
||||
docShell.isAppTab = message.data.isAppTab;
|
||||
if (docShell) {
|
||||
docShell.isAppTab = message.data.isAppTab;
|
||||
}
|
||||
});
|
||||
|
||||
let WebBrowserChrome = {
|
||||
|
@ -6,30 +6,6 @@ Components.utils.import("resource://gre/modules/Promise.jsm", this);
|
||||
|
||||
let chatbar = document.getElementById("pinnedchats");
|
||||
|
||||
function waitForCondition(condition, errorMsg) {
|
||||
let deferred = Promise.defer();
|
||||
var tries = 0;
|
||||
var interval = setInterval(function() {
|
||||
if (tries >= 30) {
|
||||
ok(false, errorMsg);
|
||||
moveOn();
|
||||
}
|
||||
var conditionPassed;
|
||||
try {
|
||||
conditionPassed = condition();
|
||||
} catch (e) {
|
||||
ok(false, e + "\n" + e.stack);
|
||||
conditionPassed = false;
|
||||
}
|
||||
if (conditionPassed) {
|
||||
moveOn();
|
||||
}
|
||||
tries++;
|
||||
}, 100);
|
||||
var moveOn = function() { clearInterval(interval); deferred.resolve(); };
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
add_chat_task(function* testOpenCloseChat() {
|
||||
let chatbox = yield promiseOpenChat("http://example.com");
|
||||
Assert.strictEqual(chatbox, chatbar.selectedChat);
|
||||
@ -115,7 +91,7 @@ add_chat_task(function* testSecondTopLevelWindow() {
|
||||
secondWindow.close();
|
||||
});
|
||||
|
||||
// Test that chats are created in the correct window.
|
||||
// Test that findChromeWindowForChats() returns the expected window.
|
||||
add_chat_task(function* testChatWindowChooser() {
|
||||
let chat = yield promiseOpenChat("http://example.com");
|
||||
Assert.equal(numChatsInWindow(window), 1, "first window has the chat");
|
||||
@ -124,42 +100,34 @@ add_chat_task(function* testChatWindowChooser() {
|
||||
let secondWindow = OpenBrowserWindow();
|
||||
yield promiseOneEvent(secondWindow, "load");
|
||||
Assert.equal(secondWindow, Chat.findChromeWindowForChats(null), "Second window is the preferred chat window");
|
||||
Assert.equal(numChatsInWindow(secondWindow), 0, "second window starts with no chats");
|
||||
yield promiseOpenChat("http://example.com#2");
|
||||
Assert.equal(numChatsInWindow(secondWindow), 1, "second window now has chats");
|
||||
Assert.equal(numChatsInWindow(window), 1, "first window still has 1 chat");
|
||||
chat.close();
|
||||
|
||||
// a bit heavy handed, but handy fixing bug 1090633
|
||||
yield waitForCondition(function () !chat.parentNode, "chat has been detached");
|
||||
Assert.equal(numChatsInWindow(window), 0, "first window now has no chats");
|
||||
// now open another chat - it should still open in the second.
|
||||
yield promiseOpenChat("http://example.com#3");
|
||||
Assert.equal(numChatsInWindow(window), 0, "first window still has no chats");
|
||||
Assert.equal(numChatsInWindow(secondWindow), 2, "second window has both chats");
|
||||
// focus the first window, and check it will be selected for future chats.
|
||||
// Bug 1090633 - there are lots of issues around focus, especially when the
|
||||
// browser itself doesn't have focus. We can end up with
|
||||
// Services.wm.getMostRecentWindow("navigator:browser") returning a different
|
||||
// window than, say, Services.focus.activeWindow. But the focus manager isn't
|
||||
// the point of this test.
|
||||
// So we simply keep focusing the first window until it is reported as the
|
||||
// most recent.
|
||||
do {
|
||||
dump("trying to force window to become the most recent.\n");
|
||||
secondWindow.focus();
|
||||
window.focus();
|
||||
yield promiseWaitForFocus();
|
||||
} while (Services.wm.getMostRecentWindow("navigator:browser") != window)
|
||||
|
||||
// focus the first window, and open yet another chat - it
|
||||
// should open in the first window.
|
||||
window.focus();
|
||||
yield promiseWaitForFocus();
|
||||
chat = yield promiseOpenChat("http://example.com#4");
|
||||
Assert.equal(numChatsInWindow(window), 1, "first window got new chat");
|
||||
chat.close();
|
||||
Assert.equal(numChatsInWindow(window), 0, "first window has no chats");
|
||||
Assert.equal(window, Chat.findChromeWindowForChats(null), "First window now the preferred chat window");
|
||||
|
||||
let privateWindow = OpenBrowserWindow({private: true});
|
||||
yield promiseOneEvent(privateWindow, "load")
|
||||
|
||||
// open a last chat - the focused window can't accept
|
||||
// chats (it's a private window), so the chat should open
|
||||
// in the window that was selected before. This is known
|
||||
// to be broken on Linux.
|
||||
chat = yield promiseOpenChat("http://example.com#5");
|
||||
let os = Services.appinfo.OS;
|
||||
const BROKEN_WM_Z_ORDER = os != "WINNT" && os != "Darwin";
|
||||
let fn = BROKEN_WM_Z_ORDER ? todo : ok;
|
||||
fn(numChatsInWindow(window) == 1, "first window got the chat");
|
||||
chat.close();
|
||||
// The focused window can't accept chats (it's a private window), so the
|
||||
// chat should open in the window that was selected before. This will be
|
||||
// either window or secondWindow (linux may choose a different one) but the
|
||||
// point is that the window is *not* the private one.
|
||||
Assert.ok(Chat.findChromeWindowForChats(null) == window ||
|
||||
Chat.findChromeWindowForChats(null) == secondWindow,
|
||||
"Private window isn't selected for new chats.");
|
||||
privateWindow.close();
|
||||
secondWindow.close();
|
||||
});
|
||||
|
@ -10,12 +10,16 @@ const CHAT_URL = "https://example.com/browser/browser/base/content/test/chat/cha
|
||||
// Is the currently opened tab focused?
|
||||
function isTabFocused() {
|
||||
let tabb = gBrowser.getBrowserForTab(gBrowser.selectedTab);
|
||||
return Services.focus.focusedWindow == tabb.contentWindow;
|
||||
// focus sucks in tests - our window may have lost focus.
|
||||
let elt = Services.focus.getFocusedElementForWindow(window, false, {});
|
||||
return elt == tabb;
|
||||
}
|
||||
|
||||
// Is the specified chat focused?
|
||||
function isChatFocused(chat) {
|
||||
return chat.chatbar._isChatFocused(chat);
|
||||
// focus sucks in tests - our window may have lost focus.
|
||||
let elt = Services.focus.getFocusedElementForWindow(window, false, {});
|
||||
return elt == chat.content;
|
||||
}
|
||||
|
||||
let chatbar = document.getElementById("pinnedchats");
|
||||
|
@ -32,19 +32,29 @@ add_task(function* test_reader_button() {
|
||||
TEST_PREFS.forEach(([name, value]) => {
|
||||
Services.prefs.setBoolPref(name, value);
|
||||
});
|
||||
Services.prefs.setBoolPref("browser.reader.detectedFirstArticle", false);
|
||||
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab();
|
||||
is_element_hidden(readerButton, "Reader mode button is not present on a new tab");
|
||||
ok(!UITour.isInfoOnTarget(window, "readerMode-urlBar"),
|
||||
"Info panel shouldn't appear without the reader mode button");
|
||||
ok(!Services.prefs.getBoolPref("browser.reader.detectedFirstArticle"),
|
||||
"Shouldn't have detected the first article");
|
||||
|
||||
// Point tab to a test page that is reader-able.
|
||||
let url = TEST_PATH + "readerModeArticle.html";
|
||||
yield promiseTabLoadEvent(tab, url);
|
||||
yield promiseWaitForCondition(() => !readerButton.hidden);
|
||||
is_element_visible(readerButton, "Reader mode button is present on a reader-able page");
|
||||
ok(UITour.isInfoOnTarget(window, "readerMode-urlBar"),
|
||||
"Info panel should be anchored at the reader mode button");
|
||||
ok(Services.prefs.getBoolPref("browser.reader.detectedFirstArticle"),
|
||||
"Should have detected the first article");
|
||||
|
||||
// Switch page into reader mode.
|
||||
readerButton.click();
|
||||
yield promiseTabLoadEvent(tab);
|
||||
ok(!UITour.isInfoOnTarget(window, "readerMode-urlBar"), "Info panel should have closed");
|
||||
|
||||
let readerUrl = gBrowser.selectedBrowser.currentURI.spec;
|
||||
ok(readerUrl.startsWith("about:reader"), "about:reader loaded after clicking reader mode button");
|
||||
|
@ -18,6 +18,8 @@ gDirectorySource = "data:application/json," + JSON.stringify({
|
||||
});
|
||||
|
||||
function runTests() {
|
||||
let origGetFrecentSitesName = DirectoryLinksProvider.getFrecentSitesName;
|
||||
DirectoryLinksProvider.getFrecentSitesName = () => "";
|
||||
let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite;
|
||||
NewTabUtils.isTopPlacesSite = (site) => false;
|
||||
|
||||
@ -84,4 +86,5 @@ function runTests() {
|
||||
yield blockCell(1);
|
||||
yield addNewTabPageTab();
|
||||
checkGrid("1,2,3,4,5,6,7,8,9");
|
||||
DirectoryLinksProvider.getFrecentSitesName = origGetFrecentSitesName;
|
||||
}
|
||||
|
@ -26,8 +26,11 @@ gDirectorySource = "data:application/json," + JSON.stringify({
|
||||
});
|
||||
|
||||
function runTests() {
|
||||
let origGetFrecentSitesName = DirectoryLinksProvider.getFrecentSitesName;
|
||||
DirectoryLinksProvider.getFrecentSitesName = () => "";
|
||||
let origEnhanced = NewTabUtils.allPages.enhanced;
|
||||
registerCleanupFunction(() => {
|
||||
DirectoryLinksProvider.getFrecentSitesName = origGetFrecentSitesName;
|
||||
Services.prefs.clearUserPref(PRELOAD_PREF);
|
||||
NewTabUtils.allPages.enhanced = origEnhanced;
|
||||
});
|
||||
|
@ -1,15 +1,14 @@
|
||||
# We still need to fix warnings in this file.
|
||||
MozLoopWorker.js
|
||||
# This file currently uses es7 features
|
||||
MozLoopAPI.jsm
|
||||
# This file currently uses a non-standard (and not on a standards track)
|
||||
# if statement within catch.
|
||||
modules/MozLoopWorker.js
|
||||
# This file currently uses es7 features eslint issue:
|
||||
# https://github.com/eslint/espree/issues/125
|
||||
modules/MozLoopAPI.jsm
|
||||
# Libs we don't need to check
|
||||
content/libs
|
||||
content/shared/libs
|
||||
standalone/content/libs
|
||||
standalone/node_modules
|
||||
# We should look at turning these on when we fix the warnings
|
||||
test/xpcshell
|
||||
test/mochitest
|
||||
# Libs we don't need to check
|
||||
test/shared/vendor
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
// Note: there are extra allowances for files used solely in Firefox desktop,
|
||||
// see content/js/.eslintrc and modules/.eslintrc
|
||||
{
|
||||
"plugins": [
|
||||
"react"
|
||||
@ -5,18 +7,6 @@
|
||||
"ecmaFeatures": {
|
||||
"forOf": true,
|
||||
"jsx": true,
|
||||
// These are on for this directory for .jsm and content/js files.
|
||||
// If adding more items here, consider turning them off for the following
|
||||
// files if they aren't supported by all browsers.
|
||||
// content/shared/.eslintrc
|
||||
// content/standalone/.eslintrc
|
||||
"blockBindings": true,
|
||||
"arrowFunctions": true,
|
||||
"destructuring": true,
|
||||
"generators": true,
|
||||
"spread": true,
|
||||
"restParams": true,
|
||||
"objectLiteralShorthandMethods": true
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
@ -43,49 +33,50 @@
|
||||
// problems they find, one at a time.
|
||||
|
||||
// Eslint built-in rules are documented at <http://eslint.org/docs/rules/>
|
||||
"camelcase": 0,
|
||||
"comma-dangle": 0,
|
||||
"comma-spacing": 0,
|
||||
"consistent-return": 0,
|
||||
"curly": 0,
|
||||
"dot-notation": 0,
|
||||
"eol-last": 0,
|
||||
"eqeqeq": 0,
|
||||
"global-strict": 0,
|
||||
"key-spacing": 0,
|
||||
"new-cap": 0,
|
||||
"no-catch-shadow": 0,
|
||||
"no-console": 0,
|
||||
"no-empty": 0,
|
||||
"no-extra-bind": 0,
|
||||
"no-extra-boolean-cast": 0,
|
||||
"no-extra-semi": 0,
|
||||
"no-multi-spaces": 0,
|
||||
"no-new": 0,
|
||||
"no-redeclare": 0,
|
||||
"no-return-assign": 0,
|
||||
"no-shadow": 0,
|
||||
"no-spaced-func": 0,
|
||||
"no-trailing-spaces": 0,
|
||||
"no-undef": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-unused-expressions": 0,
|
||||
"no-unused-vars": 0,
|
||||
"no-use-before-define": 0,
|
||||
"no-wrap-func": 0,
|
||||
"quotes": 0,
|
||||
"semi": 0,
|
||||
"semi-spacing": 0,
|
||||
"space-infix-ops": 0,
|
||||
"space-return-throw-case": 0,
|
||||
"strict": 0,
|
||||
"yoda": 0,
|
||||
"camelcase": 0, // TODO: Remove (use default)
|
||||
"comma-dangle": 0, // TODO: Remove (use default)
|
||||
"comma-spacing": 0, // TODO: Remove (use default)
|
||||
"consistent-return": 0, // TODO: Remove (use default)
|
||||
"curly": 0, // TODO: Remove (use default)
|
||||
"dot-notation": 0, // TODO: Remove (use default)
|
||||
"eol-last": 0, // TODO: Remove (use default)
|
||||
"eqeqeq": 0, // TBD. Might need to be separate for content & chrome
|
||||
"global-strict": 0, // Leave as zero (this will be unsupported in eslint 1.0.0)
|
||||
"key-spacing": 0, // TODO: Remove (use default)
|
||||
"new-cap": 0, // TODO: Remove (use default)
|
||||
"no-catch-shadow": 0, // TODO: Remove (use default)
|
||||
"no-console": 0, // Leave as 0. We use console logging in content code.
|
||||
"no-empty": 0, // TODO: Remove (use default)
|
||||
"no-extra-bind": 0, // Leave as 0
|
||||
"no-extra-boolean-cast": 0, // TODO: Remove (use default)
|
||||
"no-extra-semi": 0, // TODO: Remove (use default)
|
||||
"no-multi-spaces": 0, // TBD.
|
||||
"no-new": 0, // TODO: Remove (use default)
|
||||
"no-redeclare": 0, // TODO: Remove (use default)
|
||||
"no-return-assign": 0, // TODO: Remove (use default)
|
||||
"no-shadow": 0, // TODO: Remove (use default)
|
||||
"no-spaced-func": 0, // TODO: Remove (use default)
|
||||
"no-trailing-spaces": 0, // TODO: Remove (use default)
|
||||
"no-undef": 0, // TODO: Remove (use default)
|
||||
"no-underscore-dangle": 0, // Leave as 0. Commonly used for private variables.
|
||||
"no-unused-expressions": 0, // TODO: Remove (use default)
|
||||
"no-unused-vars": 0, // TODO: Remove (use default)
|
||||
"no-use-before-define": 0, // TODO: Remove (use default)
|
||||
"no-wrap-func": 0, // TODO: Remove (use default)
|
||||
"quotes": 0, // [2, "double", "avoid-escape"],
|
||||
"semi": 0, // TODO: Remove (use default)
|
||||
"semi-spacing": 0, // TODO: Remove (use default)
|
||||
"space-infix-ops": 0, // TODO: Remove (use default)
|
||||
"space-return-throw-case": 0, // TODO: Remove (use default)
|
||||
"strict": 0, // [2, "function"],
|
||||
"yoda": 0, // [2, "never"],
|
||||
// eslint-plugin-react rules. These are documented at
|
||||
// <https://github.com/yannickcr/eslint-plugin-react#list-of-supported-rules>
|
||||
"react/jsx-quotes": [2, "double", "avoid-escape"],
|
||||
"react/jsx-no-undef": 2,
|
||||
// Need to fix instances where this is failing.
|
||||
"react/jsx-sort-props": 0,
|
||||
"react/jsx-sort-prop-types": 0,
|
||||
"react/jsx-uses-vars": 2,
|
||||
// Need to fix the couple of instances which don't
|
||||
// currently pass this rule.
|
||||
@ -101,6 +92,7 @@
|
||||
"react/react-in-jsx-scope": 0,
|
||||
// These ones we don't want to ever enable
|
||||
"react/display-name": 0,
|
||||
"react/jsx-boolean-value": 0,
|
||||
"react/no-multi-comp": 0
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ If you install eslint and the react plugin globally:
|
||||
|
||||
You can also run it by hand in the browser/components/loop directory:
|
||||
|
||||
eslint -ext .js -ext .jsx --ext .jsm .
|
||||
eslint --ext .js --ext .jsx --ext .jsm .
|
||||
|
||||
Front-End Unit Tests
|
||||
====================
|
||||
|
15
browser/components/loop/content/js/.eslintrc
Normal file
15
browser/components/loop/content/js/.eslintrc
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"ecmaFeatures": {
|
||||
// These are on for this directory for .jsm and content/js files.
|
||||
"blockBindings": true,
|
||||
"arrowFunctions": true,
|
||||
"destructuring": true,
|
||||
"generators": true,
|
||||
"spread": true,
|
||||
"restParams": true,
|
||||
"objectLiteralShorthandMethods": true
|
||||
},
|
||||
"rules": {
|
||||
"generator-star-spacing": [2, "after"]
|
||||
}
|
||||
}
|
@ -222,7 +222,7 @@ loop.contacts = (function(_, mozL10n) {
|
||||
"disabled": !this.props.canEdit }),
|
||||
onClick: this.onItemClick, "data-action": "remove"},
|
||||
React.createElement("i", {className: "icon icon-remove"}),
|
||||
mozL10n.get("remove_contact_menu_button")
|
||||
mozL10n.get("remove_contact_menu_button2")
|
||||
)
|
||||
)
|
||||
);
|
||||
@ -587,7 +587,7 @@ loop.contacts = (function(_, mozL10n) {
|
||||
React.createElement(ButtonGroup, null,
|
||||
React.createElement(Button, {caption: this.state.importBusy
|
||||
? mozL10n.get("importing_contacts_progress_button")
|
||||
: mozL10n.get("import_contacts_button"),
|
||||
: mozL10n.get("import_contacts_button2"),
|
||||
disabled: this.state.importBusy,
|
||||
onClick: this.handleImportButtonClick},
|
||||
React.createElement("div", {className: cx({"contact-import-spinner": true,
|
||||
|
@ -222,7 +222,7 @@ loop.contacts = (function(_, mozL10n) {
|
||||
"disabled": !this.props.canEdit })}
|
||||
onClick={this.onItemClick} data-action="remove">
|
||||
<i className="icon icon-remove" />
|
||||
{mozL10n.get("remove_contact_menu_button")}
|
||||
{mozL10n.get("remove_contact_menu_button2")}
|
||||
</li>
|
||||
</ul>
|
||||
);
|
||||
@ -587,7 +587,7 @@ loop.contacts = (function(_, mozL10n) {
|
||||
<ButtonGroup>
|
||||
<Button caption={this.state.importBusy
|
||||
? mozL10n.get("importing_contacts_progress_button")
|
||||
: mozL10n.get("import_contacts_button")}
|
||||
: mozL10n.get("import_contacts_button2")}
|
||||
disabled={this.state.importBusy}
|
||||
onClick={this.handleImportButtonClick}>
|
||||
<div className={cx({"contact-import-spinner": true,
|
||||
|
@ -11,10 +11,11 @@ var loop = loop || {};
|
||||
loop.roomViews = (function(mozL10n) {
|
||||
"use strict";
|
||||
|
||||
var sharedActions = loop.shared.actions;
|
||||
var sharedMixins = loop.shared.mixins;
|
||||
var ROOM_STATES = loop.store.ROOM_STATES;
|
||||
var SCREEN_SHARE_STATES = loop.shared.utils.SCREEN_SHARE_STATES;
|
||||
var sharedActions = loop.shared.actions;
|
||||
var sharedMixins = loop.shared.mixins;
|
||||
var sharedUtils = loop.shared.utils;
|
||||
var sharedViews = loop.shared.views;
|
||||
|
||||
/**
|
||||
@ -312,13 +313,25 @@ loop.roomViews = (function(mozL10n) {
|
||||
var thumbnail = URL && URL.thumbnail || "";
|
||||
var URLDescription = URL && URL.description || "";
|
||||
var location = URL && URL.location || "";
|
||||
var locationData = null;
|
||||
if (location) {
|
||||
locationData = sharedUtils.formatURL(location);
|
||||
}
|
||||
|
||||
if (!locationData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
React.createElement("div", {className: "room-context"},
|
||||
React.createElement("img", {className: "room-context-thumbnail", src: thumbnail}),
|
||||
React.createElement("div", {className: "room-context-content"},
|
||||
React.createElement("div", {className: "room-context-label"}, mozL10n.get("context_inroom_label")),
|
||||
React.createElement("div", {className: "room-context-description"}, URLDescription),
|
||||
React.createElement("a", {className: "room-context-url", href: location, target: "_blank"}, location),
|
||||
React.createElement("a", {className: "room-context-url",
|
||||
href: location,
|
||||
target: "_blank",
|
||||
title: locationData.location}, locationData.hostname),
|
||||
this.props.roomData.roomDescription ?
|
||||
React.createElement("div", {className: "room-context-comment"}, this.props.roomData.roomDescription) :
|
||||
null,
|
||||
|
@ -11,10 +11,11 @@ var loop = loop || {};
|
||||
loop.roomViews = (function(mozL10n) {
|
||||
"use strict";
|
||||
|
||||
var sharedActions = loop.shared.actions;
|
||||
var sharedMixins = loop.shared.mixins;
|
||||
var ROOM_STATES = loop.store.ROOM_STATES;
|
||||
var SCREEN_SHARE_STATES = loop.shared.utils.SCREEN_SHARE_STATES;
|
||||
var sharedActions = loop.shared.actions;
|
||||
var sharedMixins = loop.shared.mixins;
|
||||
var sharedUtils = loop.shared.utils;
|
||||
var sharedViews = loop.shared.views;
|
||||
|
||||
/**
|
||||
@ -312,13 +313,25 @@ loop.roomViews = (function(mozL10n) {
|
||||
var thumbnail = URL && URL.thumbnail || "";
|
||||
var URLDescription = URL && URL.description || "";
|
||||
var location = URL && URL.location || "";
|
||||
var locationData = null;
|
||||
if (location) {
|
||||
locationData = sharedUtils.formatURL(location);
|
||||
}
|
||||
|
||||
if (!locationData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="room-context">
|
||||
<img className="room-context-thumbnail" src={thumbnail}/>
|
||||
<div className="room-context-content">
|
||||
<div className="room-context-label">{mozL10n.get("context_inroom_label")}</div>
|
||||
<div className="room-context-description">{URLDescription}</div>
|
||||
<a className="room-context-url" href={location} target="_blank">{location}</a>
|
||||
<a className="room-context-url"
|
||||
href={location}
|
||||
target="_blank"
|
||||
title={locationData.location}>{locationData.hostname}</a>
|
||||
{this.props.roomData.roomDescription ?
|
||||
<div className="room-context-comment">{this.props.roomData.roomDescription}</div> :
|
||||
null}
|
||||
|
@ -1,14 +0,0 @@
|
||||
{
|
||||
"ecmaFeatures": {
|
||||
// Turn off top-level items needed for the jsm files, but not wanted
|
||||
// for shared code as we can't support them.
|
||||
"blockBindings": false,
|
||||
"arrowFunctions": false,
|
||||
"destructuring": false,
|
||||
"forOf": true,
|
||||
"generators": false,
|
||||
"spread": false,
|
||||
"restParams": false,
|
||||
"objectLiteralShorthandMethods": false
|
||||
}
|
||||
}
|
@ -789,7 +789,7 @@ loop.OTSdkDriver = (function() {
|
||||
bucket = buckets.MORE_THAN_5M;
|
||||
}
|
||||
|
||||
this.mozLoop.telemetryAddValue("LOOP_TWO_WAY_MEDIA_CONN_LENGTH", bucket);
|
||||
this.mozLoop.telemetryAddValue("LOOP_TWO_WAY_MEDIA_CONN_LENGTH_1", bucket);
|
||||
this._setTwoWayMediaStartTime(this.CONNECTION_START_TIME_ALREADY_NOTED);
|
||||
|
||||
this._connectionLengthNotedCalls++;
|
||||
@ -857,7 +857,7 @@ loop.OTSdkDriver = (function() {
|
||||
return;
|
||||
}
|
||||
|
||||
this.mozLoop.telemetryAddValue("LOOP_SHARING_STATE_CHANGE", bucket);
|
||||
this.mozLoop.telemetryAddValue("LOOP_SHARING_STATE_CHANGE_1", bucket);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -271,6 +271,33 @@ var inChrome = typeof Components != "undefined" && "utils" in Components;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a url for display purposes. This includes converting the
|
||||
* domain to punycode, and then decoding the url.
|
||||
*
|
||||
* @param {String} url The url to format.
|
||||
* @return {Object} An object containing the hostname and full location.
|
||||
*/
|
||||
function formatURL(url) {
|
||||
// We're using new URL to pass this through the browser's ACE/punycode
|
||||
// processing system. If the browser considers a url to need to be
|
||||
// punycode encoded for it to be displayed, then new URL will do that for
|
||||
// us. This saves us needing our own punycode library.
|
||||
var urlObject;
|
||||
try {
|
||||
urlObject = new URL(url);
|
||||
} catch (ex) {
|
||||
console.error("Error occurred whilst parsing URL:", ex);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Finally, ensure we look good.
|
||||
return {
|
||||
hostname: urlObject.hostname,
|
||||
location: decodeURI(urlObject.href)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates and opens a mailto: url with call URL information prefilled.
|
||||
* Note: This only works for Desktop.
|
||||
@ -536,6 +563,7 @@ var inChrome = typeof Components != "undefined" && "utils" in Components;
|
||||
ROOM_INFO_FAILURES: ROOM_INFO_FAILURES,
|
||||
composeCallUrlEmail: composeCallUrlEmail,
|
||||
formatDate: formatDate,
|
||||
formatURL: formatURL,
|
||||
getBoolPreference: getBoolPreference,
|
||||
getOS: getOS,
|
||||
getOSVersion: getOSVersion,
|
||||
|
17
browser/components/loop/modules/.eslintrc
Normal file
17
browser/components/loop/modules/.eslintrc
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"ecmaFeatures": {
|
||||
"arrowFunctions": true,
|
||||
"blockBindings": true,
|
||||
"destructuring": true,
|
||||
"generators": true,
|
||||
"restParams": true,
|
||||
"spread": true,
|
||||
"objectLiteralShorthandMethods": true,
|
||||
},
|
||||
"rules": {
|
||||
"generator-star-spacing": [2, "after"],
|
||||
// We should fix the errors and enable this (set to 2)
|
||||
"no-var": 0,
|
||||
"strict": [2, "global"]
|
||||
}
|
||||
}
|
@ -13,18 +13,18 @@ BROWSER_CHROME_MANIFESTS += [
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES.loop += [
|
||||
'CardDavImporter.jsm',
|
||||
'content/shared/js/crypto.js',
|
||||
'content/shared/js/utils.js',
|
||||
'GoogleImporter.jsm',
|
||||
'LoopCalls.jsm',
|
||||
'LoopContacts.jsm',
|
||||
'LoopRooms.jsm',
|
||||
'LoopStorage.jsm',
|
||||
'MozLoopAPI.jsm',
|
||||
'MozLoopPushHandler.jsm',
|
||||
'MozLoopService.jsm',
|
||||
'MozLoopWorker.js',
|
||||
'modules/CardDavImporter.jsm',
|
||||
'modules/GoogleImporter.jsm',
|
||||
'modules/LoopCalls.jsm',
|
||||
'modules/LoopContacts.jsm',
|
||||
'modules/LoopRooms.jsm',
|
||||
'modules/LoopStorage.jsm',
|
||||
'modules/MozLoopAPI.jsm',
|
||||
'modules/MozLoopPushHandler.jsm',
|
||||
'modules/MozLoopService.jsm',
|
||||
'modules/MozLoopWorker.js',
|
||||
]
|
||||
|
||||
with Files('**'):
|
||||
|
@ -1,14 +0,0 @@
|
||||
{
|
||||
"ecmaFeatures": {
|
||||
// Turn off top-level items needed for the jsm files, but not wanted
|
||||
// for shared code as we can't support them.
|
||||
"blockBindings": false,
|
||||
"arrowFunctions": false,
|
||||
"destructuring": false,
|
||||
"forOf": true,
|
||||
"generators": false,
|
||||
"spread": false,
|
||||
"restParams": false,
|
||||
"objectLiteralShorthandMethods": false
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
var ROOM_STATES = loop.store.ROOM_STATES;
|
||||
var sharedActions = loop.shared.actions;
|
||||
var sharedMixins = loop.shared.mixins;
|
||||
var sharedUtils = loop.shared.utils;
|
||||
var sharedViews = loop.shared.views;
|
||||
|
||||
var StandaloneRoomInfoArea = React.createClass({displayName: "StandaloneRoomInfoArea",
|
||||
@ -248,7 +249,10 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var location = this.props.roomContextUrl.location;
|
||||
var locationInfo = sharedUtils.formatURL(this.props.roomContextUrl.location);
|
||||
if (!locationInfo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var cx = React.addons.classSet;
|
||||
|
||||
@ -262,9 +266,10 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
React.createElement("img", {src: this.props.roomContextUrl.thumbnail}),
|
||||
React.createElement("div", {className: "standalone-context-url-description-wrapper"},
|
||||
this.props.roomContextUrl.description,
|
||||
React.createElement("br", null), React.createElement("a", {href: location,
|
||||
React.createElement("br", null), React.createElement("a", {href: locationInfo.location,
|
||||
onClick: this.recordClick,
|
||||
target: "_blank"}, location)
|
||||
target: "_blank",
|
||||
title: locationInfo.location}, locationInfo.hostname)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -16,6 +16,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
var ROOM_STATES = loop.store.ROOM_STATES;
|
||||
var sharedActions = loop.shared.actions;
|
||||
var sharedMixins = loop.shared.mixins;
|
||||
var sharedUtils = loop.shared.utils;
|
||||
var sharedViews = loop.shared.views;
|
||||
|
||||
var StandaloneRoomInfoArea = React.createClass({
|
||||
@ -248,7 +249,10 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var location = this.props.roomContextUrl.location;
|
||||
var locationInfo = sharedUtils.formatURL(this.props.roomContextUrl.location);
|
||||
if (!locationInfo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var cx = React.addons.classSet;
|
||||
|
||||
@ -262,9 +266,10 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
<img src={this.props.roomContextUrl.thumbnail} />
|
||||
<div className="standalone-context-url-description-wrapper">
|
||||
{this.props.roomContextUrl.description}
|
||||
<br /><a href={location}
|
||||
<br /><a href={locationInfo.location}
|
||||
onClick={this.recordClick}
|
||||
target="_blank">{location}</a>
|
||||
target="_blank"
|
||||
title={locationInfo.location}>{locationInfo.hostname}</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -12,8 +12,8 @@
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"eslint": "0.18.x",
|
||||
"eslint-plugin-react": "2.0.x",
|
||||
"eslint": "0.20.x",
|
||||
"eslint-plugin-react": "2.2.x",
|
||||
"express": "3.x"
|
||||
},
|
||||
"scripts": {
|
||||
|
7
browser/components/loop/test/.eslintrc
Normal file
7
browser/components/loop/test/.eslintrc
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"rules": {
|
||||
// This is useful for some of the tests, e.g.
|
||||
// expect(new Foo()).to.Throw(/error/)
|
||||
"no-new": 0
|
||||
}
|
||||
}
|
@ -242,6 +242,23 @@ describe("loop.roomViews", function () {
|
||||
|
||||
expect(view.getDOMNode().querySelector(".room-context")).to.not.eql(null);
|
||||
});
|
||||
|
||||
it("should format the context url for display", function() {
|
||||
sandbox.stub(sharedUtils, "formatURL").returns({
|
||||
location: "location",
|
||||
hostname: "hostname"
|
||||
});
|
||||
|
||||
view = mountTestComponent({
|
||||
showContext: true,
|
||||
roomData: {
|
||||
roomContextUrls: [fakeContextURL]
|
||||
}
|
||||
});
|
||||
|
||||
expect(view.getDOMNode().querySelector(".room-context-url").textContent)
|
||||
.eql("hostname");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
17
browser/components/loop/test/mochitest/.eslintrc
Normal file
17
browser/components/loop/test/mochitest/.eslintrc
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"ecmaFeatures": {
|
||||
"arrowFunctions": true,
|
||||
"blockBindings": true,
|
||||
"destructuring": true,
|
||||
"generators": true,
|
||||
"restParams": true,
|
||||
"spread": true,
|
||||
"objectLiteralShorthandMethods": true,
|
||||
},
|
||||
"rules": {
|
||||
"generator-star-spacing": [2, "after"],
|
||||
// We should fix the errors and enable this (set to 2)
|
||||
"no-var": 0,
|
||||
"strict": [2, "global"]
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {CardDavImporter} = Cu.import("resource:///modules/loop/CardDavImporter.jsm", {});
|
||||
|
||||
const kAuth = {
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {GoogleImporter} = Cu.import("resource:///modules/loop/GoogleImporter.jsm", {});
|
||||
|
||||
let importer = new GoogleImporter();
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {LoopContacts} = Cu.import("resource:///modules/loop/LoopContacts.jsm", {});
|
||||
const {LoopStorage} = Cu.import("resource:///modules/loop/LoopStorage.jsm", {});
|
||||
|
||||
@ -221,8 +223,13 @@ add_task(function* () {
|
||||
Assert.ok(!err, "There shouldn't be an error");
|
||||
Assert.equal(result.length, toRetrieve.length, "Result list should be the same " +
|
||||
"size as the list of items to retrieve");
|
||||
|
||||
function resultFilter(c) {
|
||||
return c._guid == this._guid;
|
||||
}
|
||||
|
||||
for (let contact of toRetrieve) {
|
||||
let found = result.filter(c => c._guid == contact._guid);
|
||||
let found = result.filter(resultFilter.bind(contact));
|
||||
Assert.ok(found.length, "Contact " + contact._guid + " should be in the list");
|
||||
compareContacts(found[0], contact);
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
* effects - rather than just testing MozLoopAPI alone.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
Components.utils.import("resource://gre/modules/Promise.jsm", this);
|
||||
|
||||
add_task(loadLoopPanel);
|
||||
|
@ -6,6 +6,8 @@
|
||||
* effects - rather than just testing MozLoopAPI alone.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
Components.utils.import("resource://gre/modules/Promise.jsm", this);
|
||||
|
||||
add_task(loadLoopPanel);
|
||||
|
@ -1,21 +1,23 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* This is an integration test from navigator.mozLoop through to the end
|
||||
* effects - rather than just testing MozLoopAPI alone.
|
||||
*/
|
||||
|
||||
Components.utils.import("resource://gre/modules/Promise.jsm", this);
|
||||
|
||||
add_task(loadLoopPanel);
|
||||
|
||||
add_task(function* test_mozLoop_pluralStrings() {
|
||||
Assert.ok(gMozLoopAPI, "mozLoop should exist");
|
||||
|
||||
var strings = JSON.parse(gMozLoopAPI.getStrings("feedback_window_will_close_in2"));
|
||||
Assert.equal(gMozLoopAPI.getPluralForm(0, strings.textContent),
|
||||
"This window will close in {{countdown}} seconds");
|
||||
Assert.equal(gMozLoopAPI.getPluralForm(1, strings.textContent),
|
||||
"This window will close in {{countdown}} second");
|
||||
});
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* This is an integration test from navigator.mozLoop through to the end
|
||||
* effects - rather than just testing MozLoopAPI alone.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
Components.utils.import("resource://gre/modules/Promise.jsm", this);
|
||||
|
||||
add_task(loadLoopPanel);
|
||||
|
||||
add_task(function* test_mozLoop_pluralStrings() {
|
||||
Assert.ok(gMozLoopAPI, "mozLoop should exist");
|
||||
|
||||
var strings = JSON.parse(gMozLoopAPI.getStrings("feedback_window_will_close_in2"));
|
||||
Assert.equal(gMozLoopAPI.getPluralForm(0, strings.textContent),
|
||||
"This window will close in {{countdown}} seconds");
|
||||
Assert.equal(gMozLoopAPI.getPluralForm(1, strings.textContent),
|
||||
"This window will close in {{countdown}} second");
|
||||
});
|
||||
|
@ -6,6 +6,8 @@
|
||||
* effects - rather than just testing MozLoopAPI alone.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
Components.utils.import("resource://gre/modules/Promise.jsm", this);
|
||||
|
||||
add_task(loadLoopPanel);
|
||||
|
@ -6,6 +6,8 @@
|
||||
* effects - rather than just testing MozLoopAPI alone.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
const {SocialService} = Cu.import("resource://gre/modules/SocialService.jsm", {});
|
||||
|
||||
|
@ -4,6 +4,9 @@
|
||||
/*
|
||||
* This file contains tests for the mozLoop telemetry API.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
Components.utils.import("resource://gre/modules/Promise.jsm", this);
|
||||
|
||||
add_task(loadLoopPanel);
|
||||
@ -23,7 +26,7 @@ add_task(function* test_initialize() {
|
||||
* Tests that enumerated bucket histograms exist and can be updated.
|
||||
*/
|
||||
add_task(function* test_mozLoop_telemetryAdd_buckets() {
|
||||
let histogramId = "LOOP_TWO_WAY_MEDIA_CONN_LENGTH";
|
||||
let histogramId = "LOOP_TWO_WAY_MEDIA_CONN_LENGTH_1";
|
||||
let histogram = Services.telemetry.getHistogramById(histogramId);
|
||||
let CONN_LENGTH = gMozLoopAPI.TWO_WAY_MEDIA_CONN_LENGTH;
|
||||
|
||||
@ -49,7 +52,7 @@ add_task(function* test_mozLoop_telemetryAdd_buckets() {
|
||||
});
|
||||
|
||||
add_task(function* test_mozLoop_telemetryAdd_sharing_buckets() {
|
||||
let histogramId = "LOOP_SHARING_STATE_CHANGE";
|
||||
let histogramId = "LOOP_SHARING_STATE_CHANGE_1";
|
||||
let histogram = Services.telemetry.getHistogramById(histogramId);
|
||||
const SHARING_STATES = gMozLoopAPI.SHARING_STATE_CHANGE;
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const HAWK_TOKEN_LENGTH = 64;
|
||||
const {
|
||||
LOOP_SESSION_TYPE,
|
||||
@ -123,8 +125,8 @@ function loadLoopPanel(aOverrideOptions = {}) {
|
||||
let loopPanel = document.getElementById("loop-notification-panel");
|
||||
loopPanel.setAttribute("animate", "false");
|
||||
|
||||
// Now get the actual API.
|
||||
yield promiseGetMozLoopAPI();
|
||||
// Now get the actual API loaded into gMozLoopAPI.
|
||||
return promiseGetMozLoopAPI();
|
||||
}
|
||||
|
||||
function promiseOAuthParamsSetup(baseURL, params) {
|
||||
@ -319,7 +321,7 @@ const mockDb = {
|
||||
callback(null, details);
|
||||
},
|
||||
remove: function(guid, callback) {
|
||||
if (!guid in this._store) {
|
||||
if (!(guid in this._store)) {
|
||||
callback(new Error("Could not find _guid '" + guid + "' in database"));
|
||||
return;
|
||||
}
|
||||
|
@ -473,7 +473,7 @@ describe("loop.OTSdkDriver", function () {
|
||||
|
||||
sinon.assert.calledOnce(mozLoop.telemetryAddValue);
|
||||
sinon.assert.calledWith(mozLoop.telemetryAddValue,
|
||||
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH",
|
||||
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH_1",
|
||||
mozLoop.TWO_WAY_MEDIA_CONN_LENGTH.SHORTER_THAN_10S);
|
||||
});
|
||||
|
||||
@ -485,7 +485,7 @@ describe("loop.OTSdkDriver", function () {
|
||||
|
||||
sinon.assert.calledOnce(mozLoop.telemetryAddValue);
|
||||
sinon.assert.calledWith(mozLoop.telemetryAddValue,
|
||||
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH",
|
||||
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH_1",
|
||||
mozLoop.TWO_WAY_MEDIA_CONN_LENGTH.BETWEEN_10S_AND_30S);
|
||||
});
|
||||
|
||||
@ -497,7 +497,7 @@ describe("loop.OTSdkDriver", function () {
|
||||
|
||||
sinon.assert.calledOnce(mozLoop.telemetryAddValue);
|
||||
sinon.assert.calledWith(mozLoop.telemetryAddValue,
|
||||
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH",
|
||||
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH_1",
|
||||
mozLoop.TWO_WAY_MEDIA_CONN_LENGTH.BETWEEN_30S_AND_5M);
|
||||
});
|
||||
|
||||
@ -508,7 +508,7 @@ describe("loop.OTSdkDriver", function () {
|
||||
|
||||
sinon.assert.calledOnce(mozLoop.telemetryAddValue);
|
||||
sinon.assert.calledWith(mozLoop.telemetryAddValue,
|
||||
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH",
|
||||
"LOOP_TWO_WAY_MEDIA_CONN_LENGTH_1",
|
||||
mozLoop.TWO_WAY_MEDIA_CONN_LENGTH.MORE_THAN_5M);
|
||||
});
|
||||
|
||||
@ -530,7 +530,7 @@ describe("loop.OTSdkDriver", function () {
|
||||
|
||||
sinon.assert.calledOnce(mozLoop.telemetryAddValue);
|
||||
sinon.assert.calledWithExactly(mozLoop.telemetryAddValue,
|
||||
"LOOP_SHARING_STATE_CHANGE",
|
||||
"LOOP_SHARING_STATE_CHANGE_1",
|
||||
mozLoop.SHARING_STATE_CHANGE.WINDOW_ENABLED);
|
||||
});
|
||||
|
||||
@ -539,7 +539,7 @@ describe("loop.OTSdkDriver", function () {
|
||||
|
||||
sinon.assert.calledOnce(mozLoop.telemetryAddValue);
|
||||
sinon.assert.calledWithExactly(mozLoop.telemetryAddValue,
|
||||
"LOOP_SHARING_STATE_CHANGE",
|
||||
"LOOP_SHARING_STATE_CHANGE_1",
|
||||
mozLoop.SHARING_STATE_CHANGE.BROWSER_ENABLED);
|
||||
});
|
||||
|
||||
@ -548,7 +548,7 @@ describe("loop.OTSdkDriver", function () {
|
||||
|
||||
sinon.assert.calledOnce(mozLoop.telemetryAddValue);
|
||||
sinon.assert.calledWithExactly(mozLoop.telemetryAddValue,
|
||||
"LOOP_SHARING_STATE_CHANGE",
|
||||
"LOOP_SHARING_STATE_CHANGE_1",
|
||||
mozLoop.SHARING_STATE_CHANGE.WINDOW_DISABLED);
|
||||
});
|
||||
|
||||
@ -557,7 +557,7 @@ describe("loop.OTSdkDriver", function () {
|
||||
|
||||
sinon.assert.calledOnce(mozLoop.telemetryAddValue);
|
||||
sinon.assert.calledWithExactly(mozLoop.telemetryAddValue,
|
||||
"LOOP_SHARING_STATE_CHANGE",
|
||||
"LOOP_SHARING_STATE_CHANGE_1",
|
||||
mozLoop.SHARING_STATE_CHANGE.BROWSER_DISABLED);
|
||||
});
|
||||
});
|
||||
|
@ -145,6 +145,31 @@ describe("loop.shared.utils", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#formatURL", function() {
|
||||
it("should decode encoded URIs", function() {
|
||||
expect(sharedUtils.formatURL("http://invalid.com/?a=Foo%20Bar"))
|
||||
.eql({
|
||||
location: "http://invalid.com/?a=Foo Bar",
|
||||
hostname: "invalid.com"
|
||||
});
|
||||
});
|
||||
|
||||
it("should change some idn urls to ascii encoded", function() {
|
||||
// Note, this is based on the browser's list of what does/doesn't get
|
||||
// altered for punycode, so if the list changes this could change in the
|
||||
// future.
|
||||
expect(sharedUtils.formatURL("http://\u0261oogle.com/"))
|
||||
.eql({
|
||||
location: "http://xn--oogle-qmc.com/",
|
||||
hostname: "xn--oogle-qmc.com"
|
||||
});
|
||||
});
|
||||
|
||||
it("should return null if it the url is not valid", function() {
|
||||
expect(sharedUtils.formatURL("hinvalid//url")).eql(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#composeCallUrlEmail", function() {
|
||||
var composeEmail;
|
||||
|
||||
|
@ -13,6 +13,7 @@ describe("loop.standaloneRoomViews", function() {
|
||||
var FEEDBACK_STATES = loop.store.FEEDBACK_STATES;
|
||||
var ROOM_INFO_FAILURES = loop.shared.utils.ROOM_INFO_FAILURES;
|
||||
var sharedActions = loop.shared.actions;
|
||||
var sharedUtils = loop.shared.utils;
|
||||
|
||||
var sandbox, dispatcher, activeRoomStore, feedbackStore, dispatch;
|
||||
|
||||
@ -96,6 +97,26 @@ describe("loop.standaloneRoomViews", function() {
|
||||
expect(view.getDOMNode().querySelector(".standalone-context-url")).not.eql(null);
|
||||
});
|
||||
|
||||
it("should format the url for display", function() {
|
||||
sandbox.stub(sharedUtils, "formatURL").returns({
|
||||
location: "location",
|
||||
hostname: "hostname"
|
||||
});
|
||||
|
||||
var view = mountTestComponent({
|
||||
roomName: "Mike's room",
|
||||
roomContextUrls: [{
|
||||
description: "Mark's super page",
|
||||
location: "http://invalid.com",
|
||||
thumbnail: "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
|
||||
}]
|
||||
});
|
||||
|
||||
expect(view.getDOMNode()
|
||||
.querySelector(".standalone-context-url-description-wrapper > a").textContent)
|
||||
.eql("hostname");
|
||||
});
|
||||
|
||||
it("should not display context information if no urls are supplied", function() {
|
||||
var view = mountTestComponent({
|
||||
roomName: "Mike's room"
|
||||
|
17
browser/components/loop/test/xpcshell/.eslintrc
Normal file
17
browser/components/loop/test/xpcshell/.eslintrc
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"ecmaFeatures": {
|
||||
"arrowFunctions": true,
|
||||
"blockBindings": true,
|
||||
"destructuring": true,
|
||||
"generators": true,
|
||||
"restParams": true,
|
||||
"spread": true,
|
||||
"objectLiteralShorthandMethods": true,
|
||||
},
|
||||
"rules": {
|
||||
"generator-star-spacing": [2, "after"],
|
||||
// We should fix the errors and enable this (set to 2)
|
||||
"no-var": 0,
|
||||
"strict": [2, "global"]
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
@ -1,222 +1,223 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
{
|
||||
let dummyCallback = () => {};
|
||||
let mockWebSocket = new MockWebSocketChannel();
|
||||
let pushServerRequestCount = 0;
|
||||
|
||||
add_test(function test_initalize_offline() {
|
||||
Services.io.offline = true;
|
||||
do_check_false(MozLoopPushHandler.initialize());
|
||||
Services.io.offline = false;
|
||||
run_next_test();
|
||||
});
|
||||
"use strict";
|
||||
|
||||
add_test(function test_initalize_missing_chanid() {
|
||||
Assert.throws(() => MozLoopPushHandler.register(null, dummyCallback, dummyCallback));
|
||||
run_next_test();
|
||||
});
|
||||
let dummyCallback = () => {};
|
||||
let mockWebSocket = new MockWebSocketChannel();
|
||||
let pushServerRequestCount = 0;
|
||||
|
||||
add_test(function test_initalize_missing_regcallback() {
|
||||
Assert.throws(() => MozLoopPushHandler.register("chan-1", null, dummyCallback));
|
||||
run_next_test();
|
||||
});
|
||||
add_test(function test_initalize_offline() {
|
||||
Services.io.offline = true;
|
||||
do_check_false(MozLoopPushHandler.initialize());
|
||||
Services.io.offline = false;
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_initalize_missing_notifycallback() {
|
||||
Assert.throws(() => MozLoopPushHandler.register("chan-1", dummyCallback, null));
|
||||
run_next_test();
|
||||
});
|
||||
add_test(function test_initalize_missing_chanid() {
|
||||
Assert.throws(() => MozLoopPushHandler.register(null, dummyCallback, dummyCallback));
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_initalize_websocket() {
|
||||
do_check_true(MozLoopPushHandler.initialize({mockWebSocket: mockWebSocket}));
|
||||
MozLoopPushHandler.register(
|
||||
"chan-1",
|
||||
function(err, url, id) {
|
||||
Assert.equal(err, null, "err should be null to indicate success");
|
||||
Assert.equal(url, kEndPointUrl, "Should return push server application URL");
|
||||
Assert.equal(id, "chan-1", "Should have channel id = chan-1");
|
||||
Assert.equal(mockWebSocket.uri.prePath, kServerPushUrl,
|
||||
"Should have the url from preferences");
|
||||
Assert.equal(mockWebSocket.origin, kServerPushUrl,
|
||||
"Should have the origin url from preferences");
|
||||
Assert.equal(mockWebSocket.protocol, "push-notification",
|
||||
"Should have the protocol set to push-notifications");
|
||||
mockWebSocket.notify(15);
|
||||
},
|
||||
function(version, id) {
|
||||
Assert.equal(version, 15, "Should have version number 15");
|
||||
Assert.equal(id, "chan-1", "Should have channel id = chan-1");
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
add_test(function test_initalize_missing_regcallback() {
|
||||
Assert.throws(() => MozLoopPushHandler.register("chan-1", null, dummyCallback));
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_register_twice_same_channel() {
|
||||
MozLoopPushHandler.register(
|
||||
"chan-2",
|
||||
function(err, url, id) {
|
||||
Assert.equal(err, null, "Should return null for success");
|
||||
Assert.equal(url, kEndPointUrl, "Should return push server application URL");
|
||||
Assert.equal(id, "chan-2", "Should have channel id = chan-2");
|
||||
Assert.equal(mockWebSocket.uri.prePath, kServerPushUrl,
|
||||
"Should have the url from preferences");
|
||||
Assert.equal(mockWebSocket.origin, kServerPushUrl,
|
||||
"Should have the origin url from preferences");
|
||||
Assert.equal(mockWebSocket.protocol, "push-notification",
|
||||
"Should have the protocol set to push-notifications");
|
||||
add_test(function test_initalize_missing_notifycallback() {
|
||||
Assert.throws(() => MozLoopPushHandler.register("chan-1", dummyCallback, null));
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
// Register again for the same channel
|
||||
MozLoopPushHandler.register(
|
||||
"chan-2",
|
||||
function(err, url, id) {
|
||||
Assert.equal(err, null, "Should return null for success");
|
||||
Assert.equal(id, "chan-2", "Should have channel id = chan-2");
|
||||
run_next_test();
|
||||
},
|
||||
dummyCallback
|
||||
);
|
||||
},
|
||||
dummyCallback
|
||||
);
|
||||
});
|
||||
|
||||
// Test that the PushHander will re-connect after the near-end disconnect.
|
||||
// The uaID is cleared to force re-registration of all notification channels.
|
||||
add_test(function test_reconnect_websocket() {
|
||||
MozLoopPushHandler.uaID = undefined;
|
||||
mockWebSocket.stop();
|
||||
// Previously registered onRegistration callbacks will fire and be checked (see above).
|
||||
});
|
||||
|
||||
// Test that the PushHander will re-connect after the far-end disconnect.
|
||||
// The uaID is cleared to force re-regsitration of all notification channels.
|
||||
add_test(function test_reopen_websocket() {
|
||||
MozLoopPushHandler.uaID = undefined;
|
||||
MozLoopPushHandler.registeredChannels = {}; //Do this to force a new registration callback.
|
||||
mockWebSocket.serverClose();
|
||||
// Previously registered onRegistration callbacks will fire and be checked (see above).
|
||||
});
|
||||
|
||||
// Force a re-registration cycle and have the PushServer return a 500.
|
||||
// A retry should occur and the registration then complete.
|
||||
add_test(function test_retry_registration() {
|
||||
MozLoopPushHandler.uaID = undefined;
|
||||
mockWebSocket.initRegStatus = 500;
|
||||
mockWebSocket.stop();
|
||||
});
|
||||
|
||||
add_test(function test_reconnect_no_registration() {
|
||||
let regCnt = 0;
|
||||
MozLoopPushHandler.shutdown();
|
||||
MozLoopPushHandler.initialize({mockWebSocket: mockWebSocket});
|
||||
MozLoopPushHandler.register(
|
||||
"test-chan",
|
||||
function(err, url, id) {
|
||||
Assert.equal(++regCnt, 1, "onRegistered should only be called once");
|
||||
Assert.equal(err, null, "err should be null to indicate success");
|
||||
Assert.equal(url, kEndPointUrl, "Should return push server application URL");
|
||||
Assert.equal(id, "test-chan", "Should have channel id = test-chan");
|
||||
mockWebSocket.stop();
|
||||
setTimeout(run_next_test(), 0);
|
||||
},
|
||||
dummyCallback
|
||||
);
|
||||
});
|
||||
|
||||
add_test(function test_ping_websocket() {
|
||||
let pingReceived = false,
|
||||
socketClosed = false;
|
||||
mockWebSocket.defaultMsgHandler = (msg) => {
|
||||
pingReceived = true;
|
||||
// Do not send a ping response.
|
||||
}
|
||||
mockWebSocket.close = () => {
|
||||
socketClosed = true;
|
||||
}
|
||||
|
||||
MozLoopPushHandler.shutdown();
|
||||
MozLoopPushHandler.initialize({mockWebSocket: mockWebSocket});
|
||||
MozLoopPushHandler.register(
|
||||
"test-chan",
|
||||
function(err, url) {
|
||||
Assert.equal(err, null, "err should be null to indicate success");
|
||||
waitForCondition(() => pingReceived).then(() => {
|
||||
waitForCondition(() => socketClosed).then(() => {
|
||||
run_next_test();
|
||||
}, () => {
|
||||
do_throw("should have closed the websocket");
|
||||
});
|
||||
}, () => {
|
||||
do_throw("should have sent ping");
|
||||
});
|
||||
},
|
||||
dummyCallback
|
||||
);
|
||||
});
|
||||
|
||||
add_test(function test_retry_pushurl() {
|
||||
MozLoopPushHandler.shutdown();
|
||||
loopServer.registerPathHandler("/push-server-config", (request, response) => {
|
||||
// The PushHandler should retry the request for the push-server-config for
|
||||
// each of these cases without throwing an error.
|
||||
let n = 0;
|
||||
switch (++pushServerRequestCount) {
|
||||
case ++n:
|
||||
// Non-200 response
|
||||
response.setStatusLine(null, 500, "Retry");
|
||||
response.processAsync();
|
||||
response.finish();
|
||||
break;
|
||||
case ++n:
|
||||
// missing parameter
|
||||
response.setStatusLine(null, 200, "OK");
|
||||
response.write(JSON.stringify({pushServerURI: null}));
|
||||
response.processAsync();
|
||||
response.finish();
|
||||
break;
|
||||
case ++n:
|
||||
// json parse error
|
||||
response.setStatusLine(null, 200, "OK");
|
||||
response.processAsync();
|
||||
response.finish();
|
||||
break;
|
||||
case ++n:
|
||||
response.setStatusLine(null, 200, "OK");
|
||||
response.write(JSON.stringify({pushServerURI: kServerPushUrl}));
|
||||
response.processAsync();
|
||||
response.finish();
|
||||
|
||||
run_next_test();
|
||||
break;
|
||||
}
|
||||
add_test(function test_initalize_websocket() {
|
||||
do_check_true(MozLoopPushHandler.initialize({mockWebSocket: mockWebSocket}));
|
||||
MozLoopPushHandler.register(
|
||||
"chan-1",
|
||||
function(err, url, id) {
|
||||
Assert.equal(err, null, "err should be null to indicate success");
|
||||
Assert.equal(url, kEndPointUrl, "Should return push server application URL");
|
||||
Assert.equal(id, "chan-1", "Should have channel id = chan-1");
|
||||
Assert.equal(mockWebSocket.uri.prePath, kServerPushUrl,
|
||||
"Should have the url from preferences");
|
||||
Assert.equal(mockWebSocket.origin, kServerPushUrl,
|
||||
"Should have the origin url from preferences");
|
||||
Assert.equal(mockWebSocket.protocol, "push-notification",
|
||||
"Should have the protocol set to push-notifications");
|
||||
mockWebSocket.notify(15);
|
||||
},
|
||||
function(version, id) {
|
||||
Assert.equal(version, 15, "Should have version number 15");
|
||||
Assert.equal(id, "chan-1", "Should have channel id = chan-1");
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
do_check_true(MozLoopPushHandler.initialize({mockWebSocket: mockWebSocket}));
|
||||
});
|
||||
add_test(function test_register_twice_same_channel() {
|
||||
MozLoopPushHandler.register(
|
||||
"chan-2",
|
||||
function(err, url, id) {
|
||||
Assert.equal(err, null, "Should return null for success");
|
||||
Assert.equal(url, kEndPointUrl, "Should return push server application URL");
|
||||
Assert.equal(id, "chan-2", "Should have channel id = chan-2");
|
||||
Assert.equal(mockWebSocket.uri.prePath, kServerPushUrl,
|
||||
"Should have the url from preferences");
|
||||
Assert.equal(mockWebSocket.origin, kServerPushUrl,
|
||||
"Should have the origin url from preferences");
|
||||
Assert.equal(mockWebSocket.protocol, "push-notification",
|
||||
"Should have the protocol set to push-notifications");
|
||||
|
||||
function run_test() {
|
||||
setupFakeLoopServer();
|
||||
// Register again for the same channel
|
||||
MozLoopPushHandler.register(
|
||||
"chan-2",
|
||||
function(err, url, id) {
|
||||
Assert.equal(err, null, "Should return null for success");
|
||||
Assert.equal(id, "chan-2", "Should have channel id = chan-2");
|
||||
run_next_test();
|
||||
},
|
||||
dummyCallback
|
||||
);
|
||||
},
|
||||
dummyCallback
|
||||
);
|
||||
});
|
||||
|
||||
loopServer.registerPathHandler("/push-server-config", (request, response) => {
|
||||
// Test that the PushHander will re-connect after the near-end disconnect.
|
||||
// The uaID is cleared to force re-registration of all notification channels.
|
||||
add_test(function test_reconnect_websocket() {
|
||||
MozLoopPushHandler.uaID = undefined;
|
||||
mockWebSocket.stop();
|
||||
// Previously registered onRegistration callbacks will fire and be checked (see above).
|
||||
});
|
||||
|
||||
// Test that the PushHander will re-connect after the far-end disconnect.
|
||||
// The uaID is cleared to force re-regsitration of all notification channels.
|
||||
add_test(function test_reopen_websocket() {
|
||||
MozLoopPushHandler.uaID = undefined;
|
||||
MozLoopPushHandler.registeredChannels = {}; //Do this to force a new registration callback.
|
||||
mockWebSocket.serverClose();
|
||||
// Previously registered onRegistration callbacks will fire and be checked (see above).
|
||||
});
|
||||
|
||||
// Force a re-registration cycle and have the PushServer return a 500.
|
||||
// A retry should occur and the registration then complete.
|
||||
add_test(function test_retry_registration() {
|
||||
MozLoopPushHandler.uaID = undefined;
|
||||
mockWebSocket.initRegStatus = 500;
|
||||
mockWebSocket.stop();
|
||||
});
|
||||
|
||||
add_test(function test_reconnect_no_registration() {
|
||||
let regCnt = 0;
|
||||
MozLoopPushHandler.shutdown();
|
||||
MozLoopPushHandler.initialize({mockWebSocket: mockWebSocket});
|
||||
MozLoopPushHandler.register(
|
||||
"test-chan",
|
||||
function(err, url, id) {
|
||||
Assert.equal(++regCnt, 1, "onRegistered should only be called once");
|
||||
Assert.equal(err, null, "err should be null to indicate success");
|
||||
Assert.equal(url, kEndPointUrl, "Should return push server application URL");
|
||||
Assert.equal(id, "test-chan", "Should have channel id = test-chan");
|
||||
mockWebSocket.stop();
|
||||
setTimeout(run_next_test(), 0);
|
||||
},
|
||||
dummyCallback
|
||||
);
|
||||
});
|
||||
|
||||
add_test(function test_ping_websocket() {
|
||||
let pingReceived = false,
|
||||
socketClosed = false;
|
||||
mockWebSocket.defaultMsgHandler = (msg) => {
|
||||
pingReceived = true;
|
||||
// Do not send a ping response.
|
||||
}
|
||||
mockWebSocket.close = () => {
|
||||
socketClosed = true;
|
||||
}
|
||||
|
||||
MozLoopPushHandler.shutdown();
|
||||
MozLoopPushHandler.initialize({mockWebSocket: mockWebSocket});
|
||||
MozLoopPushHandler.register(
|
||||
"test-chan",
|
||||
function(err, url) {
|
||||
Assert.equal(err, null, "err should be null to indicate success");
|
||||
waitForCondition(() => pingReceived).then(() => {
|
||||
waitForCondition(() => socketClosed).then(() => {
|
||||
run_next_test();
|
||||
}, () => {
|
||||
do_throw("should have closed the websocket");
|
||||
});
|
||||
}, () => {
|
||||
do_throw("should have sent ping");
|
||||
});
|
||||
},
|
||||
dummyCallback
|
||||
);
|
||||
});
|
||||
|
||||
add_test(function test_retry_pushurl() {
|
||||
MozLoopPushHandler.shutdown();
|
||||
loopServer.registerPathHandler("/push-server-config", (request, response) => {
|
||||
// The PushHandler should retry the request for the push-server-config for
|
||||
// each of these cases without throwing an error.
|
||||
let n = 0;
|
||||
switch (++pushServerRequestCount) {
|
||||
case ++n:
|
||||
// Non-200 response
|
||||
response.setStatusLine(null, 500, "Retry");
|
||||
response.processAsync();
|
||||
response.finish();
|
||||
break;
|
||||
case ++n:
|
||||
// missing parameter
|
||||
response.setStatusLine(null, 200, "OK");
|
||||
response.write(JSON.stringify({pushServerURI: null}));
|
||||
response.processAsync();
|
||||
response.finish();
|
||||
break;
|
||||
case ++n:
|
||||
// json parse error
|
||||
response.setStatusLine(null, 200, "OK");
|
||||
response.processAsync();
|
||||
response.finish();
|
||||
break;
|
||||
case ++n:
|
||||
response.setStatusLine(null, 200, "OK");
|
||||
response.write(JSON.stringify({pushServerURI: kServerPushUrl}));
|
||||
response.processAsync();
|
||||
response.finish();
|
||||
});
|
||||
|
||||
Services.prefs.setCharPref("services.push.serverURL", kServerPushUrl);
|
||||
Services.prefs.setIntPref("loop.retry_delay.start", 10); // 10 ms
|
||||
Services.prefs.setIntPref("loop.retry_delay.limit", 20); // 20 ms
|
||||
Services.prefs.setIntPref("loop.ping.interval", 50); // 50 ms
|
||||
Services.prefs.setIntPref("loop.ping.timeout", 20); // 20 ms
|
||||
run_next_test();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
do_register_cleanup(function() {
|
||||
Services.prefs.clearUserPref("services.push.serverULR");
|
||||
Services.prefs.clearUserPref("loop.retry_delay.start");
|
||||
Services.prefs.clearUserPref("loop.retry_delay.limit");
|
||||
Services.prefs.clearUserPref("loop.ping.interval");
|
||||
Services.prefs.clearUserPref("loop.ping.timeout");
|
||||
});
|
||||
do_check_true(MozLoopPushHandler.initialize({mockWebSocket: mockWebSocket}));
|
||||
});
|
||||
|
||||
run_next_test();
|
||||
};
|
||||
}
|
||||
function run_test() {
|
||||
setupFakeLoopServer();
|
||||
|
||||
loopServer.registerPathHandler("/push-server-config", (request, response) => {
|
||||
response.setStatusLine(null, 200, "OK");
|
||||
response.write(JSON.stringify({pushServerURI: kServerPushUrl}));
|
||||
response.processAsync();
|
||||
response.finish();
|
||||
});
|
||||
|
||||
Services.prefs.setCharPref("services.push.serverURL", kServerPushUrl);
|
||||
Services.prefs.setIntPref("loop.retry_delay.start", 10); // 10 ms
|
||||
Services.prefs.setIntPref("loop.retry_delay.limit", 20); // 20 ms
|
||||
Services.prefs.setIntPref("loop.ping.interval", 50); // 50 ms
|
||||
Services.prefs.setIntPref("loop.ping.timeout", 20); // 20 ms
|
||||
|
||||
do_register_cleanup(function() {
|
||||
Services.prefs.clearUserPref("services.push.serverULR");
|
||||
Services.prefs.clearUserPref("loop.retry_delay.start");
|
||||
Services.prefs.clearUserPref("loop.retry_delay.limit");
|
||||
Services.prefs.clearUserPref("loop.ping.interval");
|
||||
Services.prefs.clearUserPref("loop.ping.timeout");
|
||||
});
|
||||
|
||||
run_next_test();
|
||||
};
|
||||
|
@ -2,6 +2,8 @@
|
||||
* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://services-common/utils.js");
|
||||
Cu.import("resource:///modules/loop/LoopRooms.jsm");
|
||||
Cu.import("resource:///modules/Chat.jsm");
|
||||
|
@ -2,6 +2,8 @@
|
||||
* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { LoopCallsInternal } = Cu.import("resource:///modules/loop/LoopCalls.jsm", {});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Chat",
|
||||
|
@ -2,6 +2,8 @@
|
||||
* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Chat",
|
||||
"resource:///modules/Chat.jsm");
|
||||
let openChatOrig = Chat.open;
|
||||
|
@ -2,6 +2,8 @@
|
||||
* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Chat",
|
||||
"resource:///modules/Chat.jsm");
|
||||
let openChatOrig = Chat.open;
|
||||
@ -41,7 +43,7 @@ add_test(function test_do_not_disturb_disabled_should_open_chat_window() {
|
||||
|
||||
mockPushHandler.notify(1, MozLoopService.channelIDs.callsFxA);
|
||||
|
||||
waitForCondition(function() opened).then(() => {
|
||||
waitForCondition(() => opened).then(() => {
|
||||
run_next_test();
|
||||
}, () => {
|
||||
do_throw("should have opened a chat window");
|
||||
|
@ -2,6 +2,8 @@
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* global Services, Assert */
|
||||
|
||||
"use strict";
|
||||
|
||||
const kGuestKeyPref = "loop.key";
|
||||
const kFxAKeyPref = "loop.key.fxa";
|
||||
|
||||
|
@ -1,13 +1,15 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
let startTimerCalled = false;
|
||||
|
||||
/**
|
||||
* Tests that registration doesn't happen when the expiry time is
|
||||
* not set.
|
||||
*/
|
||||
add_task(function test_initialize_no_expiry() {
|
||||
add_task(function* test_initialize_no_expiry() {
|
||||
startTimerCalled = false;
|
||||
|
||||
let initializedPromise = yield MozLoopService.initialize();
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
function test_locale() {
|
||||
// Set the pref to something controlled.
|
||||
Services.prefs.setCharPref("general.useragent.locale", "ab-CD");
|
||||
|
@ -2,6 +2,8 @@
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/*global XPCOMUtils, Services, Assert */
|
||||
|
||||
"use strict";
|
||||
|
||||
var fakeCharPrefName = "color";
|
||||
var fakeBoolPrefName = "boolean";
|
||||
var fakePrefValue = "green";
|
||||
|
@ -2,6 +2,8 @@
|
||||
* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Chat",
|
||||
"resource:///modules/Chat.jsm");
|
||||
|
||||
@ -20,7 +22,7 @@ add_test(function test_openChatWindow_on_notification() {
|
||||
|
||||
mockPushHandler.notify(1, MozLoopService.channelIDs.callsFxA);
|
||||
|
||||
waitForCondition(function() opened).then(() => {
|
||||
waitForCondition(() => opened).then(() => {
|
||||
do_check_true(opened, "should open a chat window");
|
||||
|
||||
do_check_eq(Services.prefs.getCharPref("loop.seenToS"), "seen",
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://services-common/utils.js");
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://services-common/utils.js");
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const FAKE_FXA_TOKEN_DATA = JSON.stringify({
|
||||
"token_type": "bearer",
|
||||
"access_token": "1bad3e44b12f77a88fe09f016f6a37c42e40f974bc7a8b432bb0d2f0e37e1752",
|
||||
@ -20,7 +22,7 @@ const LOOP_INITIAL_DELAY_PREF = "loop.initialDelay";
|
||||
* This file is to test restart+reauth.
|
||||
*/
|
||||
|
||||
add_task(function test_initialize_with_no_guest_rooms_and_no_auth_token() {
|
||||
add_task(function* test_initialize_with_no_guest_rooms_and_no_auth_token() {
|
||||
// Set time to be 2 seconds in the past.
|
||||
var nowSeconds = Date.now() / 1000;
|
||||
Services.prefs.setBoolPref(LOOP_CREATED_ROOM_PREF, false);
|
||||
@ -34,7 +36,7 @@ add_task(function test_initialize_with_no_guest_rooms_and_no_auth_token() {
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function test_initialize_with_created_room_and_no_auth_token() {
|
||||
add_task(function* test_initialize_with_created_room_and_no_auth_token() {
|
||||
Services.prefs.setBoolPref(LOOP_CREATED_ROOM_PREF, true);
|
||||
Services.prefs.clearUserPref(LOOP_FXA_TOKEN_PREF);
|
||||
|
||||
@ -50,7 +52,7 @@ add_task(function test_initialize_with_created_room_and_no_auth_token() {
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function test_initialize_with_invalid_fxa_token() {
|
||||
add_task(function* test_initialize_with_invalid_fxa_token() {
|
||||
Services.prefs.setCharPref(LOOP_FXA_PROFILE_PREF, FAKE_FXA_PROFILE);
|
||||
Services.prefs.setCharPref(LOOP_FXA_TOKEN_PREF, FAKE_FXA_TOKEN_DATA);
|
||||
|
||||
@ -83,7 +85,7 @@ add_task(function test_initialize_with_invalid_fxa_token() {
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function test_initialize_with_fxa_token() {
|
||||
add_task(function* test_initialize_with_fxa_token() {
|
||||
Services.prefs.setCharPref(LOOP_FXA_PROFILE_PREF, FAKE_FXA_PROFILE);
|
||||
Services.prefs.setCharPref(LOOP_FXA_TOKEN_PREF, FAKE_FXA_TOKEN_DATA);
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const LOOP_HAWK_PREF = "loop.hawk-session-token";
|
||||
const fakeSessionToken1 = "1bad3e44b12f77a88fe09f016f6a37c42e40f974bc7a8b432bb0d2f0e37e1751";
|
||||
const fakeSessionToken2 = "1bad3e44b12f77a88fe09f016f6a37c42e40f974bc7a8b432bb0d2f0e37e1750";
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Test that things behave reasonably when a reasonable Hawk-Session-Token
|
||||
* header is returned with the registration response.
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_test(function test_registration_uses_hawk_session_token() {
|
||||
Services.prefs.setCharPref("loop.hawk-session-token",
|
||||
"1bad3e44b12f77a88fe09f016f6a37c42e40f974bc7a8b432bb0d2f0e37e1750");
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// XXX should report error if Hawk-Session-Token is lexically invalid
|
||||
// (not a string of 64 hex digits) to help resist other possible injection
|
||||
// attacks. For now, however, we're just checking if it's the right length.
|
||||
|
@ -1004,12 +1004,14 @@ let gEditItemOverlay = {
|
||||
aLastModified, aItemType) {
|
||||
if (aProperty == "tags" && this._paneInfo.visibleRows.has("tagsRow"))
|
||||
this._onTagsChange(aItemId);
|
||||
else if (this._paneInfo.isItem && aProperty == "title")
|
||||
this._onItemTitleChange(aItemId, aValue);
|
||||
else (!this._paneInfo.isItem || this._paneInfo.itemId != aItemId)
|
||||
else if (!this._paneInfo.isItem || this._paneInfo.itemId != aItemId)
|
||||
return;
|
||||
|
||||
switch (aProperty) {
|
||||
case "title":
|
||||
if (this._paneInfo.isItem)
|
||||
this._onItemTitleChange(aItemId, aValue);
|
||||
break;
|
||||
case "uri":
|
||||
let newURI = NetUtil.newURI(aValue);
|
||||
if (!newURI.equals(this._paneInfo.uri)) {
|
||||
|
@ -1468,6 +1468,12 @@ this.UITour = {
|
||||
showInfoPanel.bind(this, this._correctAnchor(aAnchor.node)));
|
||||
},
|
||||
|
||||
isInfoOnTarget(aChromeWindow, aTargetName) {
|
||||
let document = aChromeWindow.document;
|
||||
let tooltip = document.getElementById("UITourTooltip");
|
||||
return tooltip.getAttribute("targetName") == aTargetName && tooltip.state != "closed";
|
||||
},
|
||||
|
||||
hideInfo: function(aWindow) {
|
||||
let document = aWindow.document;
|
||||
|
||||
|
@ -26,6 +26,9 @@ loader.lazyRequireGetter(this, "MarkersOverview",
|
||||
loader.lazyRequireGetter(this, "EventEmitter",
|
||||
"devtools/toolkit/event-emitter");
|
||||
|
||||
// TODO get rid of retro mode in bug 1160313
|
||||
loader.lazyRequireGetter(this, "Services");
|
||||
|
||||
/**
|
||||
* For line graphs
|
||||
*/
|
||||
@ -165,6 +168,24 @@ const GRAPH_DEFINITIONS = {
|
||||
}
|
||||
};
|
||||
|
||||
// TODO get rid of retro mode in bug 1160313
|
||||
const GRAPH_DEFINITIONS_RETRO = {
|
||||
memory: {
|
||||
constructor: MemoryGraph,
|
||||
selector: "#memory-overview",
|
||||
},
|
||||
framerate: {
|
||||
constructor: FramerateGraph,
|
||||
selector: "#time-framerate",
|
||||
needsBlueprints: true,
|
||||
primaryLink: true
|
||||
},
|
||||
timeline: {
|
||||
constructor: TimelineGraph,
|
||||
selector: "#markers-overview",
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A controller for orchestrating the performance's tool overview graphs. Constructs,
|
||||
* syncs, toggles displays and defines the memory, framerate and timeline view.
|
||||
@ -177,7 +198,9 @@ const GRAPH_DEFINITIONS = {
|
||||
function GraphsController ({ definition, root, getBlueprint, getTheme }) {
|
||||
this._graphs = {};
|
||||
this._enabled = new Set();
|
||||
this._definition = definition || GRAPH_DEFINITIONS;
|
||||
// TODO get rid of retro mode in bug 1160313
|
||||
let RETRO_MODE = Services.prefs.getBoolPref("devtools.performance.ui.retro-mode");
|
||||
this._definition = definition || (RETRO_MODE ? GRAPH_DEFINITIONS_RETRO : GRAPH_DEFINITIONS);
|
||||
this._root = root;
|
||||
this._getBlueprint = getBlueprint;
|
||||
this._getTheme = getTheme;
|
||||
|
@ -284,11 +284,16 @@ let PerformanceController = {
|
||||
* when the front has started to record.
|
||||
*/
|
||||
startRecording: Task.async(function *() {
|
||||
// Store retro-mode here so we can easily list true/false
|
||||
// values for reverting.
|
||||
// TODO bug 1160313
|
||||
let superMode = !this.getOption("retro-mode");
|
||||
|
||||
let options = {
|
||||
withMarkers: true,
|
||||
withMemory: this.getOption("enable-memory"),
|
||||
withMarkers: superMode ? true : false,
|
||||
withMemory: superMode ? this.getOption("enable-memory") : false,
|
||||
withTicks: this.getOption("enable-framerate"),
|
||||
withAllocations: this.getOption("enable-memory"),
|
||||
withAllocations: superMode ? this.getOption("enable-memory") : false,
|
||||
allocationsSampleProbability: this.getPref("memory-sample-probability"),
|
||||
allocationsMaxLogLength: this.getPref("memory-max-log-length"),
|
||||
bufferSize: this.getPref("profiler-buffer-size"),
|
||||
|
@ -122,5 +122,10 @@ support-files =
|
||||
[browser_profiler_tree-view-06.js]
|
||||
[browser_profiler_tree-view-07.js]
|
||||
[browser_profiler_tree-view-08.js]
|
||||
[browser_timeline_blueprint.js]
|
||||
[browser_timeline_filters.js]
|
||||
[browser_timeline-blueprint.js]
|
||||
[browser_timeline-filters.js]
|
||||
[browser_timeline-waterfall-background.js]
|
||||
[browser_timeline-waterfall-generic.js]
|
||||
[browser_timeline-waterfall-sidebar.js]
|
||||
# remove in bug 1160313
|
||||
[browser_retro-test.js]
|
||||
|
49
browser/devtools/performance/test/browser_retro-test.js
Normal file
49
browser/devtools/performance/test/browser_retro-test.js
Normal file
@ -0,0 +1,49 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that only js-calltree view is on, default, and many things are hidden
|
||||
* when in retro mode.
|
||||
*/
|
||||
const HIDDEN_OPTIONS = ["option-enable-memory", "option-invert-flame-graph", "option-show-jit-optimizations", "option-flatten-tree-recursion"];
|
||||
|
||||
Services.prefs.setBoolPref("devtools.performance.ui.retro-mode", true);
|
||||
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, PerformanceController, $, $$, JsCallTreeView } = panel.panelWin;
|
||||
|
||||
yield startRecording(panel);
|
||||
yield stopRecording(panel);
|
||||
|
||||
let model = PerformanceController.getCurrentRecording();
|
||||
|
||||
ok(model.getMemory().length === 0, "model did not record memory.");
|
||||
ok(model.getTicks().length !== 0, "model did get ticks.");
|
||||
ok(model.getAllocations().sites.length === 0, "model did get allocation data.");
|
||||
ok(model.getAllocations().timestamps.length === 0, "model did get allocation data.");
|
||||
ok(model.getAllocations().frames.length === 0, "model did get allocation data.");
|
||||
ok(model.getAllocations().counts.length === 0, "model did get allocation data.");
|
||||
|
||||
ok(DetailsView.isViewSelected(JsCallTreeView),
|
||||
"The jscalltree view is selected by default");
|
||||
|
||||
for (let option of $$("#performance-options-menupopup > menuitem")) {
|
||||
if (HIDDEN_OPTIONS.indexOf(option.id) !== -1) {
|
||||
ok(option.hidden === true, `${option.id} should be hidden.`);
|
||||
} else {
|
||||
ok(option.hidden === false, `${option.id} should be visible.`);
|
||||
}
|
||||
}
|
||||
|
||||
for (let viewbutton of $$("#performance-toolbar-controls-detail-views > toolbarbutton")) {
|
||||
ok (viewbutton.hidden === true, `${viewbutton.id} should be hidden.`);
|
||||
}
|
||||
|
||||
ok($("#markers-overview").hidden, "markers overview should be hidden.");
|
||||
ok($("#memory-overview").hidden, "memory overview should be hidden.");
|
||||
ok(!$("#time-framerate").hidden, "framerate should be shown.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the waterfall background is a 1px high canvas stretching across
|
||||
* the container bounds.
|
||||
*/
|
||||
|
||||
function spawnTest () {
|
||||
let { target, panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { $, EVENTS, PerformanceController, OverviewView, DetailsView, WaterfallView } = panel.panelWin;
|
||||
|
||||
yield startRecording(panel);
|
||||
ok(true, "Recording has started.");
|
||||
|
||||
let updated = 0;
|
||||
OverviewView.on(EVENTS.OVERVIEW_RENDERED, () => updated++);
|
||||
|
||||
ok((yield waitUntil(() => updated > 0)),
|
||||
"The overview graphs were updated a bunch of times.");
|
||||
ok((yield waitUntil(() => PerformanceController.getCurrentRecording().getMarkers().length > 0)),
|
||||
"There are some markers available.");
|
||||
|
||||
let rendered = Promise.all([
|
||||
DetailsView.selectView("waterfall"),
|
||||
once(WaterfallView, EVENTS.WATERFALL_RENDERED)
|
||||
]);
|
||||
yield stopRecording(panel);
|
||||
ok(true, "Recording has ended.");
|
||||
yield rendered;
|
||||
|
||||
// Test the waterfall background.
|
||||
|
||||
let parentWidth = $("#waterfall-view").getBoundingClientRect().width;
|
||||
let sidebarWidth = $(".waterfall-sidebar").getBoundingClientRect().width;
|
||||
let detailsWidth = $("#waterfall-details").getBoundingClientRect().width;
|
||||
let waterfallWidth = WaterfallView.waterfall._waterfallWidth;
|
||||
is(waterfallWidth, parentWidth - sidebarWidth - detailsWidth,
|
||||
"The waterfall width is correct.")
|
||||
|
||||
ok(WaterfallView.waterfall._canvas,
|
||||
"A canvas should be created after the recording ended.");
|
||||
ok(WaterfallView.waterfall._ctx,
|
||||
"A 2d context should be created after the recording ended.");
|
||||
|
||||
is(WaterfallView.waterfall._canvas.width, waterfallWidth,
|
||||
"The canvas width is correct.");
|
||||
is(WaterfallView.waterfall._canvas.height, 1,
|
||||
"The canvas height is correct.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
@ -5,22 +5,22 @@
|
||||
* Tests if the waterfall is properly built after finishing a recording.
|
||||
*/
|
||||
|
||||
add_task(function*() {
|
||||
let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
|
||||
let { $, $$, EVENTS, TimelineController } = panel.panelWin;
|
||||
function spawnTest () {
|
||||
let { target, panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { $, $$, EVENTS, PerformanceController, OverviewView, WaterfallView } = panel.panelWin;
|
||||
|
||||
yield TimelineController.toggleRecording();
|
||||
yield startRecording(panel);
|
||||
ok(true, "Recording has started.");
|
||||
|
||||
let updated = 0;
|
||||
panel.panelWin.on(EVENTS.OVERVIEW_UPDATED, () => updated++);
|
||||
OverviewView.on(EVENTS.OVERVIEW_RENDERED, () => updated++);
|
||||
|
||||
ok((yield waitUntil(() => updated > 0)),
|
||||
"The overview graphs were updated a bunch of times.");
|
||||
ok((yield waitUntil(() => TimelineController.getMarkers().length > 0)),
|
||||
ok((yield waitUntil(() => PerformanceController.getCurrentRecording().getMarkers().length > 0)),
|
||||
"There are some markers available.");
|
||||
|
||||
yield TimelineController.toggleRecording();
|
||||
yield stopRecording(panel);
|
||||
ok(true, "Recording has ended.");
|
||||
|
||||
// Test the header container.
|
||||
@ -62,4 +62,6 @@ add_task(function*() {
|
||||
"Some marker waterfall nodes should have been created.");
|
||||
ok($$(".waterfall-marker-item:not(spacer) > .waterfall-marker-bar").length,
|
||||
"Some marker color bars should have been created inside the waterfall.");
|
||||
});
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
@ -5,35 +5,34 @@
|
||||
* Tests if the sidebar is properly updated when a marker is selected.
|
||||
*/
|
||||
|
||||
add_task(function*() {
|
||||
let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
|
||||
let { $, $$, EVENTS, TimelineController, TimelineView, TIMELINE_BLUEPRINT} = panel.panelWin;
|
||||
let { L10N } = devtools.require("devtools/shared/timeline/global");
|
||||
function spawnTest () {
|
||||
let { target, panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { $, $$, EVENTS, PerformanceController, OverviewView } = panel.panelWin;
|
||||
let { L10N, TIMELINE_BLUEPRINT } = devtools.require("devtools/shared/timeline/global");
|
||||
|
||||
yield TimelineController.toggleRecording();
|
||||
yield startRecording(panel);
|
||||
ok(true, "Recording has started.");
|
||||
|
||||
yield waitUntil(() => {
|
||||
// Wait until we get 3 different markers.
|
||||
let markers = TimelineController.getMarkers();
|
||||
let markers = PerformanceController.getCurrentRecording().getMarkers();
|
||||
return markers.some(m => m.name == "Styles") &&
|
||||
markers.some(m => m.name == "Reflow") &&
|
||||
markers.some(m => m.name == "Paint");
|
||||
});
|
||||
|
||||
yield TimelineController.toggleRecording();
|
||||
yield stopRecording(panel);
|
||||
ok(true, "Recording has ended.");
|
||||
|
||||
// Select everything
|
||||
TimelineView.markersOverview.setSelection({ start: 0, end: TimelineView.markersOverview.width })
|
||||
|
||||
OverviewView.graphs.get("timeline").setSelection({ start: 0, end: OverviewView.graphs.get("timeline").width })
|
||||
|
||||
let bars = $$(".waterfall-marker-item:not(spacer) > .waterfall-marker-bar");
|
||||
let markers = TimelineController.getMarkers();
|
||||
let markers = PerformanceController.getCurrentRecording().getMarkers();
|
||||
|
||||
ok(bars.length > 2, "got at least 3 markers");
|
||||
|
||||
let sidebar = $("#timeline-waterfall-details");
|
||||
let sidebar = $("#waterfall-details");
|
||||
for (let i = 0; i < bars.length; i++) {
|
||||
let bar = bars[i];
|
||||
bar.click();
|
||||
@ -41,7 +40,7 @@ add_task(function*() {
|
||||
|
||||
let name = TIMELINE_BLUEPRINT[m.name].label;
|
||||
|
||||
is($("#timeline-waterfall-details .marker-details-type").getAttribute("value"), name,
|
||||
is($("#waterfall-details .marker-details-type").getAttribute("value"), name,
|
||||
"sidebar title matches markers name");
|
||||
|
||||
let printedStartTime = $(".marker-details-start .marker-details-labelvalue").getAttribute("value");
|
||||
@ -55,4 +54,6 @@ add_task(function*() {
|
||||
is(toMs(m.end), printedEndTime, "sidebar end time is valid");
|
||||
is(toMs(m.end - m.start), printedDuration, "sidebar duration is valid");
|
||||
}
|
||||
});
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
@ -56,6 +56,7 @@ let DEFAULT_PREFS = [
|
||||
"devtools.performance.memory.max-log-length",
|
||||
"devtools.performance.profiler.buffer-size",
|
||||
"devtools.performance.profiler.sample-frequency-khz",
|
||||
"devtools.performance.ui.retro-mode",
|
||||
].reduce((prefs, pref) => {
|
||||
prefs[pref] = Preferences.get(pref);
|
||||
return prefs;
|
||||
@ -67,6 +68,10 @@ Services.prefs.setBoolPref("devtools.performance.enabled", true);
|
||||
// be affected by this pref.
|
||||
Services.prefs.setBoolPref("devtools.debugger.log", false);
|
||||
|
||||
// Disable retro mode.
|
||||
// TODO bug 1160313
|
||||
Services.prefs.setBoolPref("devtools.performance.ui.retro-mode", false);
|
||||
|
||||
/**
|
||||
* Call manually in tests that use frame script utils after initializing
|
||||
* the tool. Must be called after initializing so we can detect
|
||||
|
@ -71,6 +71,12 @@ let DetailsSubview = {
|
||||
*/
|
||||
observedPrefs: [],
|
||||
|
||||
/**
|
||||
* Flag specifying if this view should update while the overview selection
|
||||
* area is actively being dragged by the mouse.
|
||||
*/
|
||||
shouldUpdateWhileMouseIsActive: false,
|
||||
|
||||
/**
|
||||
* Called when recording stops or is selected.
|
||||
*/
|
||||
@ -90,7 +96,14 @@ let DetailsSubview = {
|
||||
*/
|
||||
_onOverviewRangeChange: function (_, interval) {
|
||||
if (DetailsView.isViewSelected(this)) {
|
||||
let debounced = () => this.render(interval);
|
||||
let debounced = () => {
|
||||
if (!this.shouldUpdateWhileMouseIsActive && OverviewView.isMouseActive) {
|
||||
// Don't render yet, while the selection is still being dragged.
|
||||
setNamedTimeout("range-change-debounce", this.rangeChangeDebounceTime, debounced);
|
||||
} else {
|
||||
this.render(interval);
|
||||
}
|
||||
};
|
||||
setNamedTimeout("range-change-debounce", this.rangeChangeDebounceTime, debounced);
|
||||
} else {
|
||||
this.shouldUpdateWhenShown = true;
|
||||
|
@ -13,7 +13,7 @@ let JsCallTreeView = Heritage.extend(DetailsSubview, {
|
||||
"show-platform-data"
|
||||
],
|
||||
|
||||
rangeChangeDebounceTime: 50, // ms
|
||||
rangeChangeDebounceTime: 75, // ms
|
||||
|
||||
/**
|
||||
* Sets up the view with event binding.
|
||||
|
@ -9,6 +9,8 @@
|
||||
*/
|
||||
let JsFlameGraphView = Heritage.extend(DetailsSubview, {
|
||||
|
||||
shouldUpdateWhileMouseIsActive: true,
|
||||
|
||||
rerenderPrefs: [
|
||||
"invert-flame-graph",
|
||||
"flatten-tree-recursion",
|
||||
|
@ -9,6 +9,8 @@
|
||||
*/
|
||||
let MemoryFlameGraphView = Heritage.extend(DetailsSubview, {
|
||||
|
||||
shouldUpdateWhileMouseIsActive: true,
|
||||
|
||||
rerenderPrefs: [
|
||||
"invert-flame-graph",
|
||||
"flatten-tree-recursion",
|
||||
|
@ -16,7 +16,7 @@ let WaterfallView = Heritage.extend(DetailsSubview, {
|
||||
"hidden-markers"
|
||||
],
|
||||
|
||||
rangeChangeDebounceTime: 10, // ms
|
||||
rangeChangeDebounceTime: 75, // ms
|
||||
|
||||
/**
|
||||
* Sets up the view with event binding.
|
||||
@ -74,6 +74,11 @@ let WaterfallView = Heritage.extend(DetailsSubview, {
|
||||
*/
|
||||
_onMarkerSelected: function (event, marker) {
|
||||
let recording = PerformanceController.getCurrentRecording();
|
||||
// Race condition in tests due to lazy rendering of markers in the
|
||||
// waterfall? intermittent bug 1157523
|
||||
if (!recording) {
|
||||
return;
|
||||
}
|
||||
let frames = recording.getFrames();
|
||||
|
||||
if (event === "selected") {
|
||||
|
@ -94,9 +94,12 @@ let DetailsView = {
|
||||
let invalidCurrentView = false;
|
||||
|
||||
for (let [name, { view }] of Iterator(this.components)) {
|
||||
let isSupported = this._isViewSupported(name, false);
|
||||
// TODO bug 1160313 get rid of retro mode checks.
|
||||
let isRetro = PerformanceController.getOption("retro-mode");
|
||||
let isSupported = isRetro ? name === "js-calltree" : this._isViewSupported(name, false);
|
||||
|
||||
$(`toolbarbutton[data-view=${name}]`).hidden = !isSupported;
|
||||
// TODO bug 1160313 hide all view buttons, but let js-calltree still be "supported"
|
||||
$(`toolbarbutton[data-view=${name}]`).hidden = isRetro ? true : !isSupported;
|
||||
|
||||
// If the view is currently selected and not supported, go back to the
|
||||
// default view.
|
||||
|
@ -92,6 +92,16 @@ let OverviewView = {
|
||||
yield this.graphs.destroy();
|
||||
}),
|
||||
|
||||
/**
|
||||
* Returns true if any of the overview graphs have mouse dragging active,
|
||||
* false otherwise.
|
||||
*/
|
||||
get isMouseActive() {
|
||||
return (this.markersOverview && this.markersOverview.isMouseActive) ||
|
||||
(this.memoryOverview && this.memoryOverview.isMouseActive) ||
|
||||
(this.framerateGraph && this.framerateGraph.isMouseActive);
|
||||
},
|
||||
|
||||
/**
|
||||
* Disabled in the event we're using a Timeline mock, so we'll have no
|
||||
* timeline, ticks or memory data to show, so just block rendering and hide
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user