mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Merge m-c to inbound
This commit is contained in:
commit
207a21dbe8
2
CLOBBER
2
CLOBBER
@ -22,4 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 878935 landed without a UUID change (and was since backed out)
|
||||
Bug 910189 requires a clobber due to Proguard inner class errors from bug 946083.
|
||||
|
@ -280,6 +280,7 @@ pref("layers.offmainthreadcomposition.async-animations", true);
|
||||
pref("layers.async-video.enabled", true);
|
||||
pref("layers.async-pan-zoom.enabled", true);
|
||||
pref("gfx.content.azure.backends", "cairo");
|
||||
pref("layers.composer2d.enabled", true);
|
||||
#endif
|
||||
|
||||
// Web Notifications
|
||||
@ -863,6 +864,9 @@ pref("media.webspeech.synth.enabled", true);
|
||||
pref("dom.mozDownloads.enabled", true);
|
||||
pref("dom.downloads.max_retention_days", 7);
|
||||
|
||||
// Downloads API
|
||||
pref("dom.mozDownloads.enabled", true);
|
||||
|
||||
// Inactivity time in milliseconds after which we shut down the OS.File worker.
|
||||
pref("osfile.reset_worker_delay", 5000);
|
||||
|
||||
|
@ -527,6 +527,9 @@ SettingsListener.observe("debug.paint-flashing.enabled", false, function(value)
|
||||
SettingsListener.observe("layers.draw-borders", false, function(value) {
|
||||
Services.prefs.setBoolPref("layers.draw-borders", value);
|
||||
});
|
||||
SettingsListener.observe("layers.composer2d.enabled", true, function(value) {
|
||||
Services.prefs.setBoolPref("layers.composer2d.enabled", value);
|
||||
});
|
||||
|
||||
// ================ Accessibility ============
|
||||
SettingsListener.observe("accessibility.screenreader", false, function(value) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "6c2b33c8f522e2fa419011bc2de456c11e76b29f",
|
||||
"revision": "f7a78194ae8eddcc20af610abed89bac359067d2",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -1313,7 +1313,6 @@ pref("security.csp.speccompliant", true);
|
||||
// Block insecure active content on https pages
|
||||
pref("security.mixed_content.block_active_content", true);
|
||||
|
||||
|
||||
// Override the Gecko-default value of false for Firefox.
|
||||
pref("plain_text.wrap_long_lines", true);
|
||||
|
||||
@ -1331,5 +1330,9 @@ pref("network.disable.ipc.security", true);
|
||||
// CustomizableUI debug logging.
|
||||
pref("browser.uiCustomization.debug", false);
|
||||
|
||||
// The URL where remote content that composes the UI for Firefox Accounts should
|
||||
// be fetched. Must use HTTPS.
|
||||
pref("firefox.accounts.remoteUrl", "https://accounts.dev.lcip.org/flow?moar_native=true");
|
||||
|
||||
// The URL of the Firefox Accounts auth server backend
|
||||
pref("identity.fxaccounts.auth.uri", "https://api-accounts.dev.lcip.org/v1");
|
||||
|
21
browser/base/content/aboutaccounts/aboutaccounts.css
Normal file
21
browser/base/content/aboutaccounts/aboutaccounts.css
Normal file
@ -0,0 +1,21 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#remote {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
133
browser/base/content/aboutaccounts/aboutaccounts.js
Normal file
133
browser/base/content/aboutaccounts/aboutaccounts.js
Normal file
@ -0,0 +1,133 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/FxAccounts.jsm");
|
||||
|
||||
function log(msg) {
|
||||
//dump("FXA: " + msg + "\n");
|
||||
};
|
||||
|
||||
function error(msg) {
|
||||
console.log("Firefox Account Error: " + msg + "\n");
|
||||
};
|
||||
|
||||
let wrapper = {
|
||||
iframe: null,
|
||||
|
||||
init: function () {
|
||||
let iframe = document.getElementById("remote");
|
||||
this.iframe = iframe;
|
||||
iframe.addEventListener("load", this);
|
||||
|
||||
try {
|
||||
iframe.src = fxAccounts.getAccountsURI();
|
||||
} catch (e) {
|
||||
error("Couldn't init Firefox Account wrapper: " + e.message);
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent: function (evt) {
|
||||
switch (evt.type) {
|
||||
case "load":
|
||||
this.iframe.contentWindow.addEventListener("FirefoxAccountsCommand", this);
|
||||
this.iframe.removeEventListener("load", this);
|
||||
break;
|
||||
case "FirefoxAccountsCommand":
|
||||
this.handleRemoteCommand(evt);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* onLogin handler receives user credentials from the jelly after a
|
||||
* sucessful login and stores it in the fxaccounts service
|
||||
*
|
||||
* @param accountData the user's account data and credentials
|
||||
*/
|
||||
onLogin: function (accountData) {
|
||||
log("Received: 'login'. Data:" + JSON.stringify(accountData));
|
||||
|
||||
fxAccounts.setSignedInUser(accountData).then(
|
||||
() => {
|
||||
this.injectData("message", { status: "login" });
|
||||
// until we sort out a better UX, just leave the jelly page in place.
|
||||
// If the account email is not yet verified, it will tell the user to
|
||||
// go check their email, but then it will *not* change state after
|
||||
// the verification completes (the browser will begin syncing, but
|
||||
// won't notify the user). If the email has already been verified,
|
||||
// the jelly will say "Welcome! You are successfully signed in as
|
||||
// EMAIL", but it won't then say "syncing started".
|
||||
},
|
||||
(err) => this.injectData("message", { status: "error", error: err })
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* onSessionStatus sends the currently signed in user's credentials
|
||||
* to the jelly.
|
||||
*/
|
||||
onSessionStatus: function () {
|
||||
log("Received: 'session_status'.");
|
||||
|
||||
fxAccounts.getSignedInUser().then(
|
||||
(accountData) => this.injectData("message", { status: "session_status", data: accountData }),
|
||||
(err) => this.injectData("message", { status: "error", error: err })
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* onSignOut handler erases the current user's session from the fxaccounts service
|
||||
*/
|
||||
onSignOut: function () {
|
||||
log("Received: 'sign_out'.");
|
||||
|
||||
fxAccounts.signOut().then(
|
||||
() => this.injectData("message", { status: "sign_out" }),
|
||||
(err) => this.injectData("message", { status: "error", error: err })
|
||||
);
|
||||
},
|
||||
|
||||
handleRemoteCommand: function (evt) {
|
||||
log('command: ' + evt.detail.command);
|
||||
let data = evt.detail.data;
|
||||
|
||||
switch (evt.detail.command) {
|
||||
case "login":
|
||||
this.onLogin(data);
|
||||
break;
|
||||
case "session_status":
|
||||
this.onSessionStatus(data);
|
||||
break;
|
||||
case "sign_out":
|
||||
this.onSignOut(data);
|
||||
break;
|
||||
default:
|
||||
log("Unexpected remote command received: " + evt.detail.command + ". Ignoring command.");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
injectData: function (type, content) {
|
||||
let authUrl;
|
||||
try {
|
||||
authUrl = fxAccounts.getAccountsURI();
|
||||
} catch (e) {
|
||||
error("Couldn't inject data: " + e.message);
|
||||
return;
|
||||
}
|
||||
let data = {
|
||||
type: type,
|
||||
content: content
|
||||
};
|
||||
this.iframe.contentWindow.postMessage(data, authUrl);
|
||||
},
|
||||
};
|
||||
|
||||
wrapper.init();
|
||||
|
28
browser/base/content/aboutaccounts/aboutaccounts.xhtml
Normal file
28
browser/base/content/aboutaccounts/aboutaccounts.xhtml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
|
||||
%htmlDTD;
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%brandDTD;
|
||||
<!ENTITY % aboutAccountsDTD SYSTEM "chrome://browser/locale/aboutAccounts.dtd">
|
||||
%aboutAccountsDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>&aboutAccounts.pageTitle;</title>
|
||||
<link rel="icon" type="image/png" id="favicon"
|
||||
href="chrome://branding/content/icon32.png"/>
|
||||
<link rel="stylesheet"
|
||||
href="chrome://browser/content/aboutaccounts/aboutaccounts.css"
|
||||
type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe mozframetype="content" id="remote" />
|
||||
<script type="text/javascript;version=1.8"
|
||||
src="chrome://browser/content/aboutaccounts/aboutaccounts.js" />
|
||||
</body>
|
||||
</html>
|
@ -279,13 +279,20 @@ let gSyncUI = {
|
||||
*/
|
||||
|
||||
openSetup: function SUI_openSetup(wizardType) {
|
||||
let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
|
||||
if (win)
|
||||
win.focus();
|
||||
else {
|
||||
window.openDialog("chrome://browser/content/sync/setup.xul",
|
||||
"weaveSetup", "centerscreen,chrome,resizable=no",
|
||||
wizardType);
|
||||
let xps = Components.classes["@mozilla.org/weave/service;1"]
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject;
|
||||
if (xps.fxAccountsEnabled) {
|
||||
switchToTabHavingURI("about:accounts", true);
|
||||
} else {
|
||||
let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
|
||||
if (win)
|
||||
win.focus();
|
||||
else {
|
||||
window.openDialog("chrome://browser/content/sync/setup.xul",
|
||||
"weaveSetup", "centerscreen,chrome,resizable=no",
|
||||
wizardType);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -472,6 +472,13 @@ var gSyncSetup = {
|
||||
Weave.Service.identity.syncKey = Weave.Utils.generatePassphrase();
|
||||
this._handleNoScript(false);
|
||||
Weave.Svc.Prefs.set("firstSync", "newAccount");
|
||||
#ifdef XP_WIN
|
||||
#ifdef MOZ_METRO
|
||||
if (document.getElementById("metroSetupCheckbox").checked) {
|
||||
Services.metro.storeSyncInfo(email, password, Weave.Service.identity.syncKey);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
this.wizardFinish();
|
||||
return false;
|
||||
}
|
||||
|
@ -172,6 +172,20 @@
|
||||
<label class="status" value=" "/>
|
||||
</hbox>
|
||||
</row>
|
||||
#ifdef XP_WIN
|
||||
#ifdef MOZ_METRO
|
||||
<row id="metroRow" align="center">
|
||||
<spacer/>
|
||||
<hbox align="center">
|
||||
<checkbox label="&setup.setupMetro.label;"
|
||||
accesskey="&setup.setupMetro.accesskey;"
|
||||
control="weavePasswordConfirm"
|
||||
id="metroSetupCheckbox"
|
||||
checked="true"/>
|
||||
</hbox>
|
||||
</row>
|
||||
#endif
|
||||
#endif
|
||||
<row id="TOSRow" align="center">
|
||||
<spacer/>
|
||||
<hbox align="center">
|
||||
|
66
browser/base/content/test/general/Makefile.in
Normal file
66
browser/base/content/test/general/Makefile.in
Normal file
@ -0,0 +1,66 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# test_contextmenu.html and test_contextmenu_input are disabled on Linux due to bug 513558
|
||||
ifndef MOZ_WIDGET_GTK
|
||||
MOCHITEST_FILES += \
|
||||
audio.ogg \
|
||||
privateBrowsingMode.js \
|
||||
subtst_contextmenu.html \
|
||||
contextmenu_common.js \
|
||||
test_contextmenu.html \
|
||||
test_contextmenu_input.html \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
# The following tests are disabled because they are unreliable:
|
||||
# browser_bug423833.js is bug 428712
|
||||
# browser_sanitize-download-history.js is bug 432425
|
||||
#
|
||||
# browser_sanitizeDialog_treeView.js is disabled until the tree view is added
|
||||
# back to the clear recent history dialog (sanitize.xul), if it ever is (bug
|
||||
# 480169)
|
||||
|
||||
# browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
|
||||
|
||||
# browser_bug321000.js is disabled because newline handling is shaky (bug 592528)
|
||||
|
||||
# Disable tests on Windows due to frequent failures (bugs 825739, 841341)
|
||||
ifneq (windows,$(MOZ_WIDGET_TOOLKIT))
|
||||
MOCHITEST_BROWSER_FILES += \
|
||||
browser_bookmark_titles.js \
|
||||
browser_popupNotification.js \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
MOCHITEST_BROWSER_FILES += \
|
||||
browser_bug462289.js \
|
||||
$(NULL)
|
||||
else
|
||||
MOCHITEST_BROWSER_FILES += \
|
||||
browser_bug565667.js \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifdef MOZ_DATA_REPORTING
|
||||
MOCHITEST_BROWSER_FILES += \
|
||||
browser_datareporting_notification.js \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifdef MOZ_CRASHREPORTER
|
||||
MOCHITEST_BROWSER_FILES += \
|
||||
browser_pluginCrashCommentAndURL.js \
|
||||
pluginCrashCommentAndURL.html \
|
||||
browser_CTP_crashreporting.js \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
# browser_CTP_context_menu.js fails intermittently on Linux (bug 909342)
|
||||
ifndef MOZ_WIDGET_GTK
|
||||
MOCHITEST_BROWSER_FILES += \
|
||||
browser_CTP_context_menu.js \
|
||||
$(NULL)
|
||||
endif
|
@ -0,0 +1,81 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<script type="text/javascript;version=1.8">
|
||||
|
||||
function init() {
|
||||
window.addEventListener("message", function process(e) {doTest(e)}, false);
|
||||
// unless we relinquish the eventloop,
|
||||
// tests will run before the chrome event handlers are ready
|
||||
setTimeout(doTest, 0);
|
||||
}
|
||||
|
||||
function checkStatusValue(payload, expectedValue) {
|
||||
return payload.status == expectedValue;
|
||||
}
|
||||
|
||||
let tests = [
|
||||
{
|
||||
info: "Check account log in",
|
||||
event: "login",
|
||||
data: {
|
||||
email: "foo@example.com",
|
||||
uid: "1234@lcip.org",
|
||||
assertion: "foobar",
|
||||
sessionToken: "dead",
|
||||
kA: "beef",
|
||||
kB: "cafe",
|
||||
isVerified: true
|
||||
},
|
||||
payloadType: "message",
|
||||
validateResponse: function(payload) {
|
||||
return checkStatusValue(payload, "login");
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
let currentTest = -1;
|
||||
function doTest(evt) {
|
||||
if (evt) {
|
||||
if (currentTest < 0 || !evt.data.content)
|
||||
return; // not yet testing
|
||||
|
||||
let test = tests[currentTest];
|
||||
if (evt.data.type != test.payloadType)
|
||||
return; // skip unrequested events
|
||||
|
||||
let error = JSON.stringify(evt.data.content);
|
||||
let pass = false;
|
||||
try {
|
||||
pass = test.validateResponse(evt.data.content)
|
||||
} catch (e) {}
|
||||
reportResult(test.info, pass, error);
|
||||
}
|
||||
// start the next test if there are any left
|
||||
if (tests[++currentTest])
|
||||
sendToBrowser(tests[currentTest].event, tests[currentTest].data);
|
||||
else
|
||||
reportFinished();
|
||||
}
|
||||
|
||||
function reportResult(info, pass, error) {
|
||||
let data = {type: "testResult", info: info, pass: pass, error: error};
|
||||
window.parent.postMessage(data, "*");
|
||||
}
|
||||
|
||||
function reportFinished(cmd) {
|
||||
let data = {type: "testsComplete", count: tests.length};
|
||||
window.parent.postMessage(data, "*");
|
||||
}
|
||||
|
||||
function sendToBrowser(type, data) {
|
||||
let event = new CustomEvent("FirefoxAccountsCommand", {detail: {command: type, data: data}, bubbles: true});
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="init()">
|
||||
</body>
|
||||
</html>
|
@ -1,6 +1,7 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
POSTSearchEngine.xml
|
||||
accounts_testRemoteCommands.html
|
||||
alltabslistener.html
|
||||
app_bug575561.html
|
||||
app_subframe_bug575561.html
|
||||
@ -111,6 +112,7 @@ run-if = crashreporter
|
||||
[browser_CTP_nonplugins.js]
|
||||
[browser_CTP_resize.js]
|
||||
[browser_URLBarSetURI.js]
|
||||
[browser_aboutAccounts.js]
|
||||
[browser_aboutHealthReport.js]
|
||||
skip-if = os == "linux" # Bug 924307
|
||||
[browser_aboutHome.js]
|
||||
|
89
browser/base/content/test/general/browser_aboutAccounts.js
Normal file
89
browser/base/content/test/general/browser_aboutAccounts.js
Normal file
@ -0,0 +1,89 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/Promise.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
// Ensure we don't pollute prefs for next tests.
|
||||
Services.prefs.clearUserPref("firefox.accounts.remoteUrl");
|
||||
});
|
||||
|
||||
let gTests = [
|
||||
|
||||
{
|
||||
desc: "Test the remote commands",
|
||||
setup: function ()
|
||||
{
|
||||
Services.prefs.setCharPref("firefox.accounts.remoteUrl",
|
||||
"https://example.com/browser/browser/base/content/test/general/accounts_testRemoteCommands.html");
|
||||
},
|
||||
run: function ()
|
||||
{
|
||||
let deferred = Promise.defer();
|
||||
|
||||
let results = 0;
|
||||
try {
|
||||
let win = gBrowser.contentWindow;
|
||||
win.addEventListener("message", function testLoad(e) {
|
||||
if (e.data.type == "testResult") {
|
||||
ok(e.data.pass, e.data.info);
|
||||
results++;
|
||||
}
|
||||
else if (e.data.type == "testsComplete") {
|
||||
is(results, e.data.count, "Checking number of results received matches the number of tests that should have run");
|
||||
win.removeEventListener("message", testLoad, false, true);
|
||||
deferred.resolve();
|
||||
}
|
||||
|
||||
}, false, true);
|
||||
|
||||
} catch(e) {
|
||||
ok(false, "Failed to get all commands");
|
||||
deferred.reject();
|
||||
}
|
||||
return deferred.promise;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
]; // gTests
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
|
||||
Task.spawn(function () {
|
||||
for (let test of gTests) {
|
||||
info(test.desc);
|
||||
test.setup();
|
||||
|
||||
yield promiseNewTabLoadEvent("about:accounts");
|
||||
|
||||
yield test.run();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
function promiseNewTabLoadEvent(aUrl, aEventType="load")
|
||||
{
|
||||
let deferred = Promise.defer();
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab(aUrl);
|
||||
tab.linkedBrowser.addEventListener(aEventType, function load(event) {
|
||||
tab.linkedBrowser.removeEventListener(aEventType, load, true);
|
||||
let iframe = tab.linkedBrowser.contentDocument.getElementById("remote");
|
||||
iframe.addEventListener("load", function frameLoad(e) {
|
||||
iframe.removeEventListener("load", frameLoad, false);
|
||||
deferred.resolve();
|
||||
}, false);
|
||||
}, true);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -50,6 +50,9 @@ browser.jar:
|
||||
content/browser/abouthealthreport/abouthealth.js (content/abouthealthreport/abouthealth.js)
|
||||
content/browser/abouthealthreport/abouthealth.css (content/abouthealthreport/abouthealth.css)
|
||||
#endif
|
||||
content/browser/aboutaccounts/aboutaccounts.xhtml (content/aboutaccounts/aboutaccounts.xhtml)
|
||||
content/browser/aboutaccounts/aboutaccounts.js (content/aboutaccounts/aboutaccounts.js)
|
||||
content/browser/aboutaccounts/aboutaccounts.css (content/aboutaccounts/aboutaccounts.css)
|
||||
content/browser/aboutRobots-icon.png (content/aboutRobots-icon.png)
|
||||
content/browser/aboutRobots-widget-left.png (content/aboutRobots-widget-left.png)
|
||||
content/browser/aboutSocialError.xhtml (content/aboutSocialError.xhtml)
|
||||
@ -77,10 +80,10 @@ browser.jar:
|
||||
content/browser/sync/aboutSyncTabs.js (content/sync/aboutSyncTabs.js)
|
||||
content/browser/sync/aboutSyncTabs.css (content/sync/aboutSyncTabs.css)
|
||||
content/browser/sync/aboutSyncTabs-bindings.xml (content/sync/aboutSyncTabs-bindings.xml)
|
||||
content/browser/sync/setup.xul (content/sync/setup.xul)
|
||||
* content/browser/sync/setup.xul (content/sync/setup.xul)
|
||||
content/browser/sync/addDevice.js (content/sync/addDevice.js)
|
||||
content/browser/sync/addDevice.xul (content/sync/addDevice.xul)
|
||||
content/browser/sync/setup.js (content/sync/setup.js)
|
||||
* content/browser/sync/setup.js (content/sync/setup.js)
|
||||
content/browser/sync/genericChange.xul (content/sync/genericChange.xul)
|
||||
content/browser/sync/genericChange.js (content/sync/genericChange.js)
|
||||
content/browser/sync/key.xhtml (content/sync/key.xhtml)
|
||||
|
@ -90,6 +90,8 @@ static RedirEntry kRedirMap[] = {
|
||||
{ "healthreport", "chrome://browser/content/abouthealthreport/abouthealth.xhtml",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
#endif
|
||||
{ "accounts", "chrome://browser/content/aboutaccounts/aboutaccounts.xhtml",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
{ "app-manager", "chrome://browser/content/devtools/app-manager/index.xul",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
{ "customizing", "chrome://browser/content/customizableui/aboutCustomizing.xhtml",
|
||||
|
@ -106,6 +106,7 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "permissions", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "preferences", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "downloads", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "accounts", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "healthreport", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
#endif
|
||||
|
@ -1695,7 +1695,10 @@ let CustomizableUIInternal = {
|
||||
|
||||
// If the widget doesn't have an existing placement, and it hasn't been
|
||||
// seen before, then add it to its default area so it can be used.
|
||||
if (autoAdd && !widget.currentArea && !gSeenWidgets.has(widget.id)) {
|
||||
// If the widget is not removable, we *have* to add it to its default
|
||||
// area here.
|
||||
let canBeAutoAdded = autoAdd && !gSeenWidgets.has(widget.id);
|
||||
if (!widget.currentArea && (!widget.removable || canBeAutoAdded)) {
|
||||
this.beginBatchUpdate();
|
||||
try {
|
||||
gSeenWidgets.add(widget.id);
|
||||
|
@ -48,4 +48,5 @@ skip-if = os == "mac"
|
||||
[browser_944887_destroyWidget_should_destroy_in_palette.js]
|
||||
[browser_945739_showInPrivateBrowsing_customize_mode.js]
|
||||
[browser_947987_removable_default.js]
|
||||
[browser_948985_non_removable_defaultArea.js]
|
||||
[browser_panel_toggle.js]
|
||||
|
@ -0,0 +1,32 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const kWidgetId = "test-destroy-non-removable-defaultArea";
|
||||
|
||||
add_task(function() {
|
||||
let spec = {id: kWidgetId, label: "Test non-removable defaultArea re-adding.",
|
||||
removable: false, defaultArea: CustomizableUI.AREA_NAVBAR};
|
||||
CustomizableUI.createWidget(spec);
|
||||
let placement = CustomizableUI.getPlacementOfWidget(kWidgetId);
|
||||
ok(placement, "Should have placed the widget.");
|
||||
is(placement && placement.area, CustomizableUI.AREA_NAVBAR, "Widget should be in navbar");
|
||||
CustomizableUI.destroyWidget(kWidgetId);
|
||||
CustomizableUI.removeWidgetFromArea(kWidgetId);
|
||||
|
||||
CustomizableUI.createWidget(spec);
|
||||
ok(placement, "Should have placed the widget.");
|
||||
is(placement && placement.area, CustomizableUI.AREA_NAVBAR, "Widget should be in navbar");
|
||||
CustomizableUI.destroyWidget(kWidgetId);
|
||||
CustomizableUI.removeWidgetFromArea(kWidgetId);
|
||||
|
||||
const kPrefCustomizationAutoAdd = "browser.uiCustomization.autoAdd";
|
||||
Services.prefs.setBoolPref(kPrefCustomizationAutoAdd, false);
|
||||
CustomizableUI.createWidget(spec);
|
||||
ok(placement, "Should have placed the widget.");
|
||||
is(placement && placement.area, CustomizableUI.AREA_NAVBAR, "Widget should be in navbar");
|
||||
CustomizableUI.destroyWidget(kWidgetId);
|
||||
CustomizableUI.removeWidgetFromArea(kWidgetId);
|
||||
Services.prefs.clearUserPref(kPrefCustomizationAutoAdd);
|
||||
});
|
||||
|
@ -583,6 +583,25 @@ nsBrowserContentHandler.prototype = {
|
||||
|
||||
overridePage = overridePage.replace("%OLD_VERSION%", old_mstone);
|
||||
break;
|
||||
|
||||
// Temporary case for Australis whatsnew
|
||||
case OVERRIDE_NEW_BUILD_ID:
|
||||
let locale = "en-US";
|
||||
try {
|
||||
locale = Services.prefs.getCharPref("general.useragent.locale");
|
||||
} catch (e) {}
|
||||
|
||||
let showedAustralisWhatsNew = false;
|
||||
try {
|
||||
showedAustralisWhatsNew = Services.prefs.getBoolPref("browser.showedAustralisWhatsNew");
|
||||
} catch(e) {}
|
||||
|
||||
// Show the Australis whatsnew page for en-US if we haven't yet shown it
|
||||
if (!showedAustralisWhatsNew && locale == "en-US") {
|
||||
Services.prefs.setBoolPref("browser.showedAustralisWhatsNew", true);
|
||||
overridePage = "https://www.mozilla.org/en-US/firefox/29.0a1/whatsnew/";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (ex) {}
|
||||
|
@ -91,6 +91,13 @@ let gSyncPane = {
|
||||
if (Weave.Status.service == Weave.CLIENT_NOT_CONFIGURED ||
|
||||
Weave.Svc.Prefs.get("firstSync", "") == "notReady") {
|
||||
this.page = PAGE_NO_ACCOUNT;
|
||||
let service = Components.classes["@mozilla.org/weave/service;1"]
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject;
|
||||
// no concept of "pair" in an fxAccounts world.
|
||||
if (service.fxAccountsEnabled) {
|
||||
document.getElementById("pairDevice").hidden = true;
|
||||
}
|
||||
} else if (Weave.Status.login == Weave.LOGIN_FAILED_INVALID_PASSPHRASE ||
|
||||
Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) {
|
||||
this.needsUpdate();
|
||||
@ -148,13 +155,22 @@ let gSyncPane = {
|
||||
* "reset" -- reset sync
|
||||
*/
|
||||
openSetup: function (wizardType) {
|
||||
let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
|
||||
if (win)
|
||||
win.focus();
|
||||
else {
|
||||
window.openDialog("chrome://browser/content/sync/setup.xul",
|
||||
"weaveSetup", "centerscreen,chrome,resizable=no",
|
||||
wizardType);
|
||||
let service = Components.classes["@mozilla.org/weave/service;1"]
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject;
|
||||
|
||||
if (service.fxAccountsEnabled) {
|
||||
let win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
win.switchToTabHavingURI("about:accounts", true);
|
||||
} else {
|
||||
let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
|
||||
if (win)
|
||||
win.focus();
|
||||
else {
|
||||
window.openDialog("chrome://browser/content/sync/setup.xul",
|
||||
"weaveSetup", "centerscreen,chrome,resizable=no",
|
||||
wizardType);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -38,10 +38,12 @@
|
||||
<label class="text-link"
|
||||
onclick="event.stopPropagation(); gSyncPane.openSetup(null);"
|
||||
value="&setupButton.label;"/>
|
||||
<separator/>
|
||||
<label class="text-link"
|
||||
onclick="event.stopPropagation(); gSyncPane.openSetup('pair');"
|
||||
value="&pairDevice.label;"/>
|
||||
<vbox id="pairDevice">
|
||||
<separator/>
|
||||
<label class="text-link"
|
||||
onclick="event.stopPropagation(); gSyncPane.openSetup('pair');"
|
||||
value="&pairDevice.label;"/>
|
||||
</vbox>
|
||||
<spacer flex="3"/>
|
||||
</vbox>
|
||||
|
||||
|
@ -91,6 +91,13 @@ let gSyncPane = {
|
||||
if (Weave.Status.service == Weave.CLIENT_NOT_CONFIGURED ||
|
||||
Weave.Svc.Prefs.get("firstSync", "") == "notReady") {
|
||||
this.page = PAGE_NO_ACCOUNT;
|
||||
let service = Components.classes["@mozilla.org/weave/service;1"]
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject;
|
||||
// no concept of "pair" in an fxAccounts world.
|
||||
if (service.fxAccountsEnabled) {
|
||||
document.getElementById("pairDevice").hidden = true;
|
||||
}
|
||||
} else if (Weave.Status.login == Weave.LOGIN_FAILED_INVALID_PASSPHRASE ||
|
||||
Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) {
|
||||
this.needsUpdate();
|
||||
@ -151,13 +158,24 @@ let gSyncPane = {
|
||||
* "reset" -- reset sync
|
||||
*/
|
||||
openSetup: function (wizardType) {
|
||||
let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
|
||||
if (win) {
|
||||
win.focus();
|
||||
let service = Components.classes["@mozilla.org/weave/service;1"]
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject;
|
||||
|
||||
if (service.fxAccountsEnabled) {
|
||||
let win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
win.switchToTabHavingURI("about:accounts", true);
|
||||
// seeing as we are doing this in a tab we close the prefs dialog.
|
||||
window.close();
|
||||
} else {
|
||||
window.openDialog("chrome://browser/content/sync/setup.xul",
|
||||
"weaveSetup", "centerscreen,chrome,resizable=no",
|
||||
wizardType);
|
||||
let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
|
||||
if (win) {
|
||||
win.focus();
|
||||
} else {
|
||||
window.openDialog("chrome://browser/content/sync/setup.xul",
|
||||
"weaveSetup", "centerscreen,chrome,resizable=no",
|
||||
wizardType);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -47,10 +47,12 @@
|
||||
<label class="text-link"
|
||||
onclick="event.stopPropagation(); gSyncPane.openSetup(null);"
|
||||
value="&setupButton.label;"/>
|
||||
<separator/>
|
||||
<label class="text-link"
|
||||
onclick="event.stopPropagation(); gSyncPane.openSetup('pair');"
|
||||
value="&pairDevice.label;"/>
|
||||
<vbox id="pairDevice">
|
||||
<separator/>
|
||||
<label class="text-link"
|
||||
onclick="event.stopPropagation(); gSyncPane.openSetup('pair');"
|
||||
value="&pairDevice.label;"/>
|
||||
</vbox>
|
||||
<spacer flex="3"/>
|
||||
</vbox>
|
||||
|
||||
|
@ -182,9 +182,6 @@ let TabStateInternal = {
|
||||
tabData.index = history.index;
|
||||
}
|
||||
|
||||
// Copy data from the persistent cache.
|
||||
this._copyFromPersistentCache(tab, tabData);
|
||||
|
||||
// If we're still the latest async collection for the given tab and
|
||||
// the cache hasn't been filled by collect() in the meantime, let's
|
||||
// fill the cache with the data we received.
|
||||
@ -193,6 +190,16 @@ let TabStateInternal = {
|
||||
this._pendingCollections.delete(browser);
|
||||
}
|
||||
|
||||
// Copy data from the persistent cache. We need to create an explicit
|
||||
// copy of the |tabData| object so that the properties injected by
|
||||
// |_copyFromPersistentCache| don't end up in the non-persistent cache.
|
||||
// The persistent cache does not store "null" values, so any values that
|
||||
// have been cleared by the frame script would not be overriden by
|
||||
// |_copyFromPersistentCache|. These two caches are only an interim
|
||||
// solution and the non-persistent one will go away soon.
|
||||
tabData = Utils.copy(tabData);
|
||||
this._copyFromPersistentCache(tab, tabData);
|
||||
|
||||
throw new Task.Result(tabData);
|
||||
}.bind(this));
|
||||
|
||||
@ -219,7 +226,16 @@ let TabStateInternal = {
|
||||
throw new TypeError("Expecting a tab");
|
||||
}
|
||||
if (TabStateCache.has(tab)) {
|
||||
return TabStateCache.get(tab);
|
||||
// Copy data from the persistent cache. We need to create an explicit
|
||||
// copy of the |tabData| object so that the properties injected by
|
||||
// |_copyFromPersistentCache| don't end up in the non-persistent cache.
|
||||
// The persistent cache does not store "null" values, so any values that
|
||||
// have been cleared by the frame script would not be overriden by
|
||||
// |_copyFromPersistentCache|. These two caches are only an interim
|
||||
// solution and the non-persistent one will go away soon.
|
||||
let tabData = Utils.copy(TabStateCache.get(tab));
|
||||
this._copyFromPersistentCache(tab, tabData);
|
||||
return tabData;
|
||||
}
|
||||
|
||||
let tabData = this._collectSyncUncached(tab);
|
||||
@ -228,6 +244,16 @@ let TabStateInternal = {
|
||||
TabStateCache.set(tab, tabData);
|
||||
}
|
||||
|
||||
// Copy data from the persistent cache. We need to create an explicit
|
||||
// copy of the |tabData| object so that the properties injected by
|
||||
// |_copyFromPersistentCache| don't end up in the non-persistent cache.
|
||||
// The persistent cache does not store "null" values, so any values that
|
||||
// have been cleared by the frame script would not be overriden by
|
||||
// |_copyFromPersistentCache|. These two caches are only an interim
|
||||
// solution and the non-persistent one will go away soon.
|
||||
tabData = Utils.copy(tabData);
|
||||
this._copyFromPersistentCache(tab, tabData);
|
||||
|
||||
// Prevent all running asynchronous collections from filling the cache.
|
||||
// Every asynchronous data collection started before a collectSync() call
|
||||
// can't expect to retrieve different data than the sync call. That's why
|
||||
@ -262,7 +288,13 @@ let TabStateInternal = {
|
||||
* up-to-date.
|
||||
*/
|
||||
clone: function (tab) {
|
||||
return this._collectSyncUncached(tab, {includePrivateData: true});
|
||||
let options = {includePrivateData: true};
|
||||
let tabData = this._collectSyncUncached(tab, options);
|
||||
|
||||
// Copy data from the persistent cache.
|
||||
this._copyFromPersistentCache(tab, tabData, options);
|
||||
|
||||
return tabData;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -305,9 +337,6 @@ let TabStateInternal = {
|
||||
tabData.index = history.index;
|
||||
}
|
||||
|
||||
// Copy data from the persistent cache.
|
||||
this._copyFromPersistentCache(tab, tabData, options);
|
||||
|
||||
return tabData;
|
||||
},
|
||||
|
||||
|
@ -64,5 +64,16 @@ this.Utils = Object.freeze({
|
||||
map.set(otherKey, value);
|
||||
map.delete(key);
|
||||
}
|
||||
},
|
||||
|
||||
// Copies all properties of a given object to a new one and returns it.
|
||||
copy: function (from) {
|
||||
let to = {};
|
||||
|
||||
for (let key of Object.keys(from)) {
|
||||
to[key] = from[key];
|
||||
}
|
||||
|
||||
return to;
|
||||
}
|
||||
});
|
||||
|
@ -1928,7 +1928,10 @@ Breakpoints.prototype = {
|
||||
let disabledPromise = this._disabled.get(identifier);
|
||||
if (disabledPromise) {
|
||||
disabledPromise.then(({ conditionalExpression: previousValue }) => {
|
||||
aBreakpointClient.conditionalExpression = previousValue;
|
||||
// Setting a falsy conditional expression is redundant.
|
||||
if (previousValue) {
|
||||
aBreakpointClient.conditionalExpression = previousValue;
|
||||
}
|
||||
});
|
||||
this._disabled.delete(identifier);
|
||||
}
|
||||
|
@ -100,6 +100,7 @@ support-files =
|
||||
[browser_dbg_conditional-breakpoints-01.js]
|
||||
[browser_dbg_conditional-breakpoints-02.js]
|
||||
[browser_dbg_conditional-breakpoints-03.js]
|
||||
[browser_dbg_conditional-breakpoints-04.js]
|
||||
[browser_dbg_controller-evaluate-01.js]
|
||||
[browser_dbg_controller-evaluate-02.js]
|
||||
[browser_dbg_debugger-statement.js]
|
||||
|
@ -77,13 +77,13 @@ function test() {
|
||||
.getAttribute("value"), "getName",
|
||||
"Should have the right property name for 'getName' in person.");
|
||||
is(personNode.get("getName").target.querySelector(".value")
|
||||
.getAttribute("value"), "Function",
|
||||
.getAttribute("value"), "_pfactory/<.getName()",
|
||||
"'getName' in person should have the right value.");
|
||||
is(personNode.get("getFoo").target.querySelector(".name")
|
||||
.getAttribute("value"), "getFoo",
|
||||
"Should have the right property name for 'getFoo' in person.");
|
||||
is(personNode.get("getFoo").target.querySelector(".value")
|
||||
.getAttribute("value"), "Function",
|
||||
.getAttribute("value"), "_pfactory/<.getFoo()",
|
||||
"'getFoo' in person should have the right value.");
|
||||
|
||||
// Expand the function nodes. This causes their properties to be
|
||||
|
@ -0,0 +1,84 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Make sure that conditional breakpoints with undefined expressions
|
||||
* are stored as plain breakpoints when re-enabling them.
|
||||
*/
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_conditional-breakpoints.html";
|
||||
|
||||
function test() {
|
||||
let gTab, gDebuggee, gPanel, gDebugger;
|
||||
let gSources, gBreakpoints, gLocation;
|
||||
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPanel = aPanel;
|
||||
gDebugger = gPanel.panelWin;
|
||||
gSources = gDebugger.DebuggerView.Sources;
|
||||
gBreakpoints = gDebugger.DebuggerController.Breakpoints;
|
||||
|
||||
gLocation = { url: gSources.selectedValue, line: 18 };
|
||||
|
||||
waitForSourceAndCaretAndScopes(gPanel, ".html", 17)
|
||||
.then(addBreakpoint)
|
||||
.then(setDummyConditional)
|
||||
.then(() => {
|
||||
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_REMOVED);
|
||||
toggleBreakpoint();
|
||||
return finished;
|
||||
})
|
||||
.then(() => {
|
||||
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_ADDED);
|
||||
toggleBreakpoint();
|
||||
return finished;
|
||||
})
|
||||
.then(testConditionalExpressionOnClient)
|
||||
.then(() => {
|
||||
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.CONDITIONAL_BREAKPOINT_POPUP_SHOWING);
|
||||
openConditionalPopup();
|
||||
finished.then(() => ok(false, "The popup shouldn't have opened."));
|
||||
return waitForTime(1000);
|
||||
})
|
||||
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
|
||||
.then(null, aError => {
|
||||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
});
|
||||
|
||||
gDebuggee.ermahgerd();
|
||||
});
|
||||
|
||||
function addBreakpoint() {
|
||||
return gPanel.addBreakpoint(gLocation);
|
||||
}
|
||||
|
||||
function setDummyConditional(aClient) {
|
||||
// This happens when a conditional expression input popup is shown
|
||||
// but the user doesn't type anything into it.
|
||||
aClient.conditionalExpression = "";
|
||||
}
|
||||
|
||||
function toggleBreakpoint() {
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
gDebugger.document.querySelector(".dbg-breakpoint-checkbox"),
|
||||
gDebugger);
|
||||
}
|
||||
|
||||
function openConditionalPopup() {
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
gDebugger.document.querySelector(".dbg-breakpoint"),
|
||||
gDebugger);
|
||||
}
|
||||
|
||||
function testConditionalExpressionOnClient() {
|
||||
return gBreakpoints._getAdded(gLocation).then(aClient => {
|
||||
if ("conditionalExpression" in aClient) {
|
||||
ok(false, "A conditional expression shouldn't have been set.");
|
||||
} else {
|
||||
ok(true, "The conditional expression wasn't set, as expected.");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -30,13 +30,15 @@ function testPause() {
|
||||
|
||||
gDebugger.gThreadClient.addOneTimeListener("paused", () => {
|
||||
gToolbox.selectTool("webconsole").then(() => {
|
||||
ok(gToolboxTab.classList.contains("highlighted"),
|
||||
ok(gToolboxTab.hasAttribute("highlighted") &&
|
||||
gToolboxTab.getAttribute("highlighted") == "true",
|
||||
"The highlighted class is present");
|
||||
ok(!gToolboxTab.hasAttribute("selected") ||
|
||||
gToolboxTab.getAttribute("selected") != "true",
|
||||
"The tab is not selected");
|
||||
}).then(() => gToolbox.selectTool("jsdebugger")).then(() => {
|
||||
ok(gToolboxTab.classList.contains("highlighted"),
|
||||
ok(gToolboxTab.hasAttribute("highlighted") &&
|
||||
gToolboxTab.getAttribute("highlighted") == "true",
|
||||
"The highlighted class is present");
|
||||
ok(gToolboxTab.hasAttribute("selected") &&
|
||||
gToolboxTab.getAttribute("selected") == "true",
|
||||
|
@ -78,13 +78,15 @@ function testPause() {
|
||||
"Debugger's tab got selected.");
|
||||
}
|
||||
gToolbox.selectTool("webconsole").then(() => {
|
||||
ok(gToolboxTab.classList.contains("highlighted"),
|
||||
ok(gToolboxTab.hasAttribute("highlighted") &&
|
||||
gToolboxTab.getAttribute("highlighted") == "true",
|
||||
"The highlighted class is present");
|
||||
ok(!gToolboxTab.hasAttribute("selected") ||
|
||||
gToolboxTab.getAttribute("selected") != "true",
|
||||
"The tab is not selected");
|
||||
}).then(() => gToolbox.selectTool("jsdebugger")).then(() => {
|
||||
ok(gToolboxTab.classList.contains("highlighted"),
|
||||
ok(gToolboxTab.hasAttribute("highlighted") &&
|
||||
gToolboxTab.getAttribute("highlighted") == "true",
|
||||
"The highlighted class is present");
|
||||
ok(gToolboxTab.hasAttribute("selected") &&
|
||||
gToolboxTab.getAttribute("selected") == "true",
|
||||
@ -100,7 +102,8 @@ function testPause() {
|
||||
function testResume() {
|
||||
gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
|
||||
gToolbox.selectTool("webconsole").then(() => {
|
||||
ok(!gToolboxTab.classList.contains("highlighted"),
|
||||
ok(!gToolboxTab.hasAttribute("highlighted") ||
|
||||
gToolboxTab.getAttribute("highlighted") != "true",
|
||||
"The highlighted class is not present now after the resume");
|
||||
ok(!gToolboxTab.hasAttribute("selected") ||
|
||||
gToolboxTab.getAttribute("selected") != "true",
|
||||
|
@ -58,7 +58,7 @@ function testPauseOnExceptionsDisabled() {
|
||||
|
||||
is(innerNodes[0].querySelector(".name").getAttribute("value"), "this",
|
||||
"Should have the right property name for 'this'.");
|
||||
is(innerNodes[0].querySelector(".value").getAttribute("value"), "HTMLButtonElement",
|
||||
is(innerNodes[0].querySelector(".value").getAttribute("value"), "<button>",
|
||||
"Should have the right property value for 'this'.");
|
||||
|
||||
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.AFTER_FRAMES_CLEARED).then(() => {
|
||||
@ -124,7 +124,7 @@ function testPauseOnExceptionsEnabled() {
|
||||
|
||||
is(innerNodes[0].querySelector(".name").getAttribute("value"), "this",
|
||||
"Should have the right property name for 'this'.");
|
||||
is(innerNodes[0].querySelector(".value").getAttribute("value"), "HTMLButtonElement",
|
||||
is(innerNodes[0].querySelector(".value").getAttribute("value"), "<button>",
|
||||
"Should have the right property value for 'this'.");
|
||||
|
||||
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.AFTER_FRAMES_CLEARED).then(() => {
|
||||
|
@ -79,7 +79,7 @@ function testPauseOnExceptionsAfterReload() {
|
||||
|
||||
is(innerNodes[0].querySelector(".name").getAttribute("value"), "this",
|
||||
"Should have the right property name for 'this'.");
|
||||
is(innerNodes[0].querySelector(".value").getAttribute("value"), "HTMLButtonElement",
|
||||
is(innerNodes[0].querySelector(".value").getAttribute("value"), "<button>",
|
||||
"Should have the right property value for 'this'.");
|
||||
|
||||
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.AFTER_FRAMES_CLEARED).then(() => {
|
||||
|
@ -22,16 +22,16 @@ function test() {
|
||||
.then(() => initialChecks())
|
||||
.then(() => testModification("a", "1"))
|
||||
.then(() => testModification("{ a: 1 }", "Object"))
|
||||
.then(() => testModification("[a]", "Array"))
|
||||
.then(() => testModification("[a]", "Array[1]"))
|
||||
.then(() => testModification("b", "Object"))
|
||||
.then(() => testModification("b.a", "1"))
|
||||
.then(() => testModification("c.a", "1"))
|
||||
.then(() => testModification("Infinity", "Infinity"))
|
||||
.then(() => testModification("NaN", "NaN"))
|
||||
.then(() => testModification("new Function", "Function"))
|
||||
.then(() => testModification("new Function", "anonymous()"))
|
||||
.then(() => testModification("+0", "0"))
|
||||
.then(() => testModification("-0", "-0"))
|
||||
.then(() => testModification("Object.keys({})", "Array"))
|
||||
.then(() => testModification("Object.keys({})", "Array[0]"))
|
||||
.then(() => testModification("document.title", '"Debugger test page"'))
|
||||
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
|
||||
.then(null, aError => {
|
||||
|
@ -89,14 +89,16 @@ function testExpandVariables() {
|
||||
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_PROPERTIES, 3).then(() => {
|
||||
is(thisVar.get("window").target.querySelector(".name").getAttribute("value"), "window",
|
||||
"Should have the right property name for 'window'.");
|
||||
is(thisVar.get("window").target.querySelector(".value").getAttribute("value"), "Window",
|
||||
is(thisVar.get("window").target.querySelector(".value").getAttribute("value"),
|
||||
"Window \u2192 doc_frame-parameters.html",
|
||||
"Should have the right property value for 'window'.");
|
||||
ok(thisVar.get("window").target.querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for 'window'.");
|
||||
|
||||
is(thisVar.get("document").target.querySelector(".name").getAttribute("value"), "document",
|
||||
"Should have the right property name for 'document'.");
|
||||
is(thisVar.get("document").target.querySelector(".value").getAttribute("value"), "HTMLDocument",
|
||||
is(thisVar.get("document").target.querySelector(".value").getAttribute("value"),
|
||||
"HTMLDocument \u2192 doc_frame-parameters.html",
|
||||
"Should have the right property value for 'document'.");
|
||||
ok(thisVar.get("document").target.querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for 'document'.");
|
||||
|
@ -56,7 +56,8 @@ function testScopeVariables() {
|
||||
|
||||
is(localEnums[0].querySelector(".name").getAttribute("value"), "this",
|
||||
"Should have the right property name for 'this'.");
|
||||
is(localEnums[0].querySelector(".value").getAttribute("value"), "Window",
|
||||
is(localEnums[0].querySelector(".value").getAttribute("value"),
|
||||
"Window \u2192 doc_frame-parameters.html",
|
||||
"Should have the right property value for 'this'.");
|
||||
ok(localEnums[0].querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for 'this'.");
|
||||
@ -192,7 +193,8 @@ function testArgumentsProperties() {
|
||||
|
||||
is(argsNonEnums[0].querySelector(".name").getAttribute("value"), "callee",
|
||||
"Should have the right property name for 'callee'.");
|
||||
is(argsNonEnums[0].querySelector(".value").getAttribute("value"), "Function",
|
||||
is(argsNonEnums[0].querySelector(".value").getAttribute("value"),
|
||||
"test(aArg,bArg,cArg,dArg,eArg,fArg)",
|
||||
"Should have the right property name for 'callee'.");
|
||||
ok(argsNonEnums[0].querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for 'callee'.");
|
||||
@ -518,14 +520,16 @@ function testGetterSetterObject() {
|
||||
|
||||
is(propNonEnums[0].querySelector(".name").getAttribute("value"), "get",
|
||||
"Should have the right property name for 'get'.");
|
||||
is(propNonEnums[0].querySelector(".value").getAttribute("value"), "Function",
|
||||
is(propNonEnums[0].querySelector(".value").getAttribute("value"),
|
||||
"test/myVar.prop()",
|
||||
"Should have the right property value for 'get'.");
|
||||
ok(propNonEnums[0].querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for 'get'.");
|
||||
|
||||
is(propNonEnums[1].querySelector(".name").getAttribute("value"), "set",
|
||||
"Should have the right property name for 'set'.");
|
||||
is(propNonEnums[1].querySelector(".value").getAttribute("value"), "Function",
|
||||
is(propNonEnums[1].querySelector(".value").getAttribute("value"),
|
||||
"test/myVar.prop(val)",
|
||||
"Should have the right property value for 'set'.");
|
||||
ok(propNonEnums[1].querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for 'set'.");
|
||||
|
@ -71,12 +71,14 @@ function testGlobalScope() {
|
||||
|
||||
is(globalScope.get("window").target.querySelector(".name").getAttribute("value"), "window",
|
||||
"Should have the right property name for 'window'.");
|
||||
is(globalScope.get("window").target.querySelector(".value").getAttribute("value"), "Window",
|
||||
is(globalScope.get("window").target.querySelector(".value").getAttribute("value"),
|
||||
"Window \u2192 doc_frame-parameters.html",
|
||||
"Should have the right property value for 'window'.");
|
||||
|
||||
is(globalScope.get("document").target.querySelector(".name").getAttribute("value"), "document",
|
||||
"Should have the right property name for 'document'.");
|
||||
is(globalScope.get("document").target.querySelector(".value").getAttribute("value"), "HTMLDocument",
|
||||
is(globalScope.get("document").target.querySelector(".value").getAttribute("value"),
|
||||
"HTMLDocument \u2192 doc_frame-parameters.html",
|
||||
"Should have the right property value for 'document'.");
|
||||
|
||||
is(globalScope.get("undefined").target.querySelector(".name").getAttribute("value"), "undefined",
|
||||
@ -123,12 +125,14 @@ function testWindowVariable() {
|
||||
|
||||
is(windowVar.get("window").target.querySelector(".name").getAttribute("value"), "window",
|
||||
"Should have the right property name for 'window'.");
|
||||
is(windowVar.get("window").target.querySelector(".value").getAttribute("value"), "Window",
|
||||
is(windowVar.get("window").target.querySelector(".value").getAttribute("value"),
|
||||
"Window \u2192 doc_frame-parameters.html",
|
||||
"Should have the right property value for 'window'.");
|
||||
|
||||
is(windowVar.get("document").target.querySelector(".name").getAttribute("value"), "document",
|
||||
"Should have the right property name for 'document'.");
|
||||
is(windowVar.get("document").target.querySelector(".value").getAttribute("value"), "HTMLDocument",
|
||||
is(windowVar.get("document").target.querySelector(".value").getAttribute("value"),
|
||||
"HTMLDocument \u2192 doc_frame-parameters.html",
|
||||
"Should have the right property value for 'document'.");
|
||||
|
||||
is(windowVar.get("undefined").target.querySelector(".name").getAttribute("value"), "undefined",
|
||||
|
@ -57,7 +57,8 @@ function testFirstWithScope() {
|
||||
|
||||
is(withEnums[0].querySelector(".name").getAttribute("value"), "this",
|
||||
"Should have the right property name for 'this'.");
|
||||
is(withEnums[0].querySelector(".value").getAttribute("value"), "Window",
|
||||
is(withEnums[0].querySelector(".value").getAttribute("value"),
|
||||
"Window \u2192 doc_with-frame.html",
|
||||
"Should have the right property value for 'this'.");
|
||||
ok(withEnums[0].querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for 'this'.");
|
||||
@ -131,7 +132,7 @@ function testSecondWithScope() {
|
||||
|
||||
is(secondWithScope.get("random").target.querySelector(".name").getAttribute("value"), "random",
|
||||
"Should have the right property name for 'random'.");
|
||||
is(secondWithScope.get("random").target.querySelector(".value").getAttribute("value"), "Function",
|
||||
is(secondWithScope.get("random").target.querySelector(".value").getAttribute("value"), "random()",
|
||||
"Should have the right property value for 'random'.");
|
||||
ok(secondWithScope.get("random").target.querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for 'random'.");
|
||||
|
@ -54,7 +54,7 @@ function initialChecks() {
|
||||
|
||||
is(arrayVar.target.querySelector(".name").getAttribute("value"), "largeArray",
|
||||
"Should have the right property name for 'largeArray'.");
|
||||
is(arrayVar.target.querySelector(".value").getAttribute("value"), "Int8Array",
|
||||
is(arrayVar.target.querySelector(".value").getAttribute("value"), "Int8Array[10000]",
|
||||
"Should have the right property value for 'largeArray'.");
|
||||
ok(arrayVar.target.querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for 'largeArray'.");
|
||||
|
@ -62,7 +62,7 @@ function performTest() {
|
||||
|
||||
is(buttonVar.target.querySelector(".name").getAttribute("value"), "button",
|
||||
"Should have the right property name for 'button'.");
|
||||
is(buttonVar.target.querySelector(".value").getAttribute("value"), "HTMLButtonElement",
|
||||
is(buttonVar.target.querySelector(".value").getAttribute("value"), "<button>",
|
||||
"Should have the right property value for 'button'.");
|
||||
ok(buttonVar.target.querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for 'button'.");
|
||||
@ -76,7 +76,8 @@ function performTest() {
|
||||
|
||||
is(documentVar.target.querySelector(".name").getAttribute("value"), "document",
|
||||
"Should have the right property name for 'document'.");
|
||||
is(documentVar.target.querySelector(".value").getAttribute("value"), "HTMLDocument",
|
||||
is(documentVar.target.querySelector(".value").getAttribute("value"),
|
||||
"HTMLDocument \u2192 doc_frame-parameters.html",
|
||||
"Should have the right property value for 'document'.");
|
||||
ok(documentVar.target.querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for 'document'.");
|
||||
@ -98,14 +99,14 @@ function performTest() {
|
||||
|
||||
is(buttonVar.get("childNodes").target.querySelector(".name").getAttribute("value"), "childNodes",
|
||||
"Should have the right property name for 'childNodes'.");
|
||||
is(buttonVar.get("childNodes").target.querySelector(".value").getAttribute("value"), "NodeList",
|
||||
is(buttonVar.get("childNodes").target.querySelector(".value").getAttribute("value"), "NodeList[1]",
|
||||
"Should have the right property value for 'childNodes'.");
|
||||
ok(buttonVar.get("childNodes").target.querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for 'childNodes'.");
|
||||
|
||||
is(buttonVar.get("onclick").target.querySelector(".name").getAttribute("value"), "onclick",
|
||||
"Should have the right property name for 'onclick'.");
|
||||
is(buttonVar.get("onclick").target.querySelector(".value").getAttribute("value"), "Function",
|
||||
is(buttonVar.get("onclick").target.querySelector(".value").getAttribute("value"), "onclick(event)",
|
||||
"Should have the right property value for 'onclick'.");
|
||||
ok(buttonVar.get("onclick").target.querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for 'onclick'.");
|
||||
@ -119,7 +120,7 @@ function performTest() {
|
||||
|
||||
is(documentVar.get("childNodes").target.querySelector(".name").getAttribute("value"), "childNodes",
|
||||
"Should have the right property name for 'childNodes'.");
|
||||
is(documentVar.get("childNodes").target.querySelector(".value").getAttribute("value"), "NodeList",
|
||||
is(documentVar.get("childNodes").target.querySelector(".value").getAttribute("value"), "NodeList[3]",
|
||||
"Should have the right property value for 'childNodes'.");
|
||||
ok(documentVar.get("childNodes").target.querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for 'childNodes'.");
|
||||
@ -144,7 +145,7 @@ function performTest() {
|
||||
|
||||
is(buttonAsProtoProtoVar.target.querySelector(".name").getAttribute("value"), "__proto__",
|
||||
"Should have the right property name for '__proto__'.");
|
||||
is(buttonAsProtoProtoVar.target.querySelector(".value").getAttribute("value"), "HTMLButtonElement",
|
||||
is(buttonAsProtoProtoVar.target.querySelector(".value").getAttribute("value"), "<button>",
|
||||
"Should have the right property value for '__proto__'.");
|
||||
ok(buttonAsProtoProtoVar.target.querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for '__proto__'.");
|
||||
@ -173,14 +174,14 @@ function performTest() {
|
||||
|
||||
is(buttonAsProtoProtoVar.get("childNodes").target.querySelector(".name").getAttribute("value"), "childNodes",
|
||||
"Should have the right property name for 'childNodes'.");
|
||||
is(buttonAsProtoProtoVar.get("childNodes").target.querySelector(".value").getAttribute("value"), "NodeList",
|
||||
is(buttonAsProtoProtoVar.get("childNodes").target.querySelector(".value").getAttribute("value"), "NodeList[1]",
|
||||
"Should have the right property value for 'childNodes'.");
|
||||
ok(buttonAsProtoProtoVar.get("childNodes").target.querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for 'childNodes'.");
|
||||
|
||||
is(buttonAsProtoProtoVar.get("onclick").target.querySelector(".name").getAttribute("value"), "onclick",
|
||||
"Should have the right property name for 'onclick'.");
|
||||
is(buttonAsProtoProtoVar.get("onclick").target.querySelector(".value").getAttribute("value"), "Function",
|
||||
is(buttonAsProtoProtoVar.get("onclick").target.querySelector(".value").getAttribute("value"), "onclick(event)",
|
||||
"Should have the right property value for 'onclick'.");
|
||||
ok(buttonAsProtoProtoVar.get("onclick").target.querySelector(".value").className.contains("token-other"),
|
||||
"Should have the right token class for 'onclick'.");
|
||||
|
@ -65,20 +65,20 @@ function unhighlightTab(toolId) {
|
||||
|
||||
function checkHighlighted(toolId) {
|
||||
let tab = toolbox.doc.getElementById("toolbox-tab-" + toolId);
|
||||
ok(tab.classList.contains("highlighted"), "The highlighted class is present");
|
||||
ok(tab.hasAttribute("highlighted"), "The highlighted attribute is present");
|
||||
ok(!tab.hasAttribute("selected") || tab.getAttribute("selected") != "true",
|
||||
"The tab is not selected");
|
||||
}
|
||||
|
||||
function checkNoHighlightWhenSelected(toolId) {
|
||||
let tab = toolbox.doc.getElementById("toolbox-tab-" + toolId);
|
||||
ok(tab.classList.contains("highlighted"), "The highlighted class is present");
|
||||
ok(tab.hasAttribute("highlighted"), "The highlighted attribute is present");
|
||||
ok(tab.hasAttribute("selected") && tab.getAttribute("selected") == "true",
|
||||
"and the tab is selected, so the orange glow will not be present.");
|
||||
}
|
||||
|
||||
function checkNoHighlight(toolId) {
|
||||
let tab = toolbox.doc.getElementById("toolbox-tab-" + toolId);
|
||||
ok(!tab.classList.contains("highlighted"),
|
||||
"The highlighted class is not present");
|
||||
ok(!tab.hasAttribute("highlighted"),
|
||||
"The highlighted attribute is not present");
|
||||
}
|
||||
|
@ -796,7 +796,7 @@ Toolbox.prototype = {
|
||||
*/
|
||||
highlightTool: function(id) {
|
||||
let tab = this.doc.getElementById("toolbox-tab-" + id);
|
||||
tab && tab.classList.add("highlighted");
|
||||
tab && tab.setAttribute("highlighted", "true");
|
||||
},
|
||||
|
||||
/**
|
||||
@ -807,7 +807,7 @@ Toolbox.prototype = {
|
||||
*/
|
||||
unhighlightTool: function(id) {
|
||||
let tab = this.doc.getElementById("toolbox-tab-" + id);
|
||||
tab && tab.classList.remove("highlighted");
|
||||
tab && tab.removeAttribute("highlighted");
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -27,6 +27,9 @@ Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "devtools",
|
||||
"resource://gre/modules/devtools/Loader.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
||||
"resource://gre/modules/PluralForm.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
|
||||
"@mozilla.org/widget/clipboardhelper;1",
|
||||
"nsIClipboardHelper");
|
||||
@ -2346,7 +2349,10 @@ Variable.prototype = Heritage.extend(Scope.prototype, {
|
||||
this._valueLabel.classList.remove(VariablesView.getClass(prevGrip));
|
||||
}
|
||||
this._valueGrip = aGrip;
|
||||
this._valueString = VariablesView.getString(aGrip, true);
|
||||
this._valueString = VariablesView.getString(aGrip, {
|
||||
concise: true,
|
||||
noEllipsis: true,
|
||||
});
|
||||
this._valueClassName = VariablesView.getClass(aGrip);
|
||||
|
||||
this._valueLabel.classList.add(this._valueClassName);
|
||||
@ -3118,12 +3124,16 @@ VariablesView.getGrip = function(aValue) {
|
||||
*
|
||||
* @param any aGrip
|
||||
* @see Variable.setGrip
|
||||
* @param boolean aConciseFlag
|
||||
* Return a concisely formatted property string.
|
||||
* @param object aOptions
|
||||
* Options:
|
||||
* - concise: boolean that tells you want a concisely formatted string.
|
||||
* - noStringQuotes: boolean that tells to not quote strings.
|
||||
* - noEllipsis: boolean that tells to not add an ellipsis after the
|
||||
* initial text of a longString.
|
||||
* @return string
|
||||
* The formatted property string.
|
||||
*/
|
||||
VariablesView.getString = function(aGrip, aConciseFlag) {
|
||||
VariablesView.getString = function(aGrip, aOptions = {}) {
|
||||
if (aGrip && typeof aGrip == "object") {
|
||||
switch (aGrip.type) {
|
||||
case "undefined":
|
||||
@ -3133,18 +3143,30 @@ VariablesView.getString = function(aGrip, aConciseFlag) {
|
||||
case "-Infinity":
|
||||
case "-0":
|
||||
return aGrip.type;
|
||||
case "longString":
|
||||
return "\"" + aGrip.initial + "\"";
|
||||
default:
|
||||
if (!aConciseFlag) {
|
||||
return "[" + aGrip.type + " " + aGrip.class + "]";
|
||||
let stringifier = VariablesView.stringifiers.byType[aGrip.type];
|
||||
if (stringifier) {
|
||||
let result = stringifier(aGrip, aOptions);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return aGrip.class;
|
||||
|
||||
if (aGrip.displayString) {
|
||||
return VariablesView.getString(aGrip.displayString, aOptions);
|
||||
}
|
||||
|
||||
if (aGrip.type == "object" && aOptions.concise) {
|
||||
return aGrip.class;
|
||||
}
|
||||
|
||||
return "[" + aGrip.type + " " + aGrip.class + "]";
|
||||
}
|
||||
}
|
||||
|
||||
switch (typeof aGrip) {
|
||||
case "string":
|
||||
return "\"" + aGrip + "\"";
|
||||
return VariablesView.stringifiers.byType.string(aGrip, aOptions);
|
||||
case "boolean":
|
||||
return aGrip ? "true" : "false";
|
||||
case "number":
|
||||
@ -3156,6 +3178,367 @@ VariablesView.getString = function(aGrip, aConciseFlag) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The VariablesView stringifiers are used by VariablesView.getString(). These
|
||||
* are organized by object type, object class and by object actor preview kind.
|
||||
* Some objects share identical ways for previews, for example Arrays, Sets and
|
||||
* NodeLists.
|
||||
*
|
||||
* Any stringifier function must return a string. If null is returned, * then
|
||||
* the default stringifier will be used. When invoked, the stringifier is
|
||||
* given the same two arguments as those given to VariablesView.getString().
|
||||
*/
|
||||
VariablesView.stringifiers = {};
|
||||
|
||||
VariablesView.stringifiers.byType = {
|
||||
string: function(aGrip, {noStringQuotes}) {
|
||||
if (noStringQuotes) {
|
||||
return aGrip;
|
||||
}
|
||||
return uneval(aGrip);
|
||||
},
|
||||
|
||||
longString: function({initial}, {noStringQuotes, noEllipsis}) {
|
||||
let ellipsis = noEllipsis ? "" : Scope.ellipsis;
|
||||
if (noStringQuotes) {
|
||||
return initial + ellipsis;
|
||||
}
|
||||
let result = uneval(initial);
|
||||
if (!ellipsis) {
|
||||
return result;
|
||||
}
|
||||
return result.substr(0, result.length - 1) + ellipsis + '"';
|
||||
},
|
||||
|
||||
object: function(aGrip, aOptions) {
|
||||
let {preview} = aGrip;
|
||||
let stringifier;
|
||||
if (preview && preview.kind) {
|
||||
stringifier = VariablesView.stringifiers.byObjectKind[preview.kind];
|
||||
}
|
||||
if (!stringifier && aGrip.class) {
|
||||
stringifier = VariablesView.stringifiers.byObjectClass[aGrip.class];
|
||||
}
|
||||
if (stringifier) {
|
||||
return stringifier(aGrip, aOptions);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
}; // VariablesView.stringifiers.byType
|
||||
|
||||
VariablesView.stringifiers.byObjectClass = {
|
||||
Function: function(aGrip, {concise}) {
|
||||
// TODO: Bug 948484 - support arrow functions and ES6 generators
|
||||
|
||||
let name = aGrip.userDisplayName || aGrip.displayName || aGrip.name || "";
|
||||
name = VariablesView.getString(name, { noStringQuotes: true });
|
||||
|
||||
// TODO: Bug 948489 - Support functions with destructured parameters and
|
||||
// rest parameters
|
||||
let params = aGrip.parameterNames || "";
|
||||
if (!concise) {
|
||||
return "function " + name + "(" + params + ")";
|
||||
}
|
||||
return (name || "function ") + "(" + params + ")";
|
||||
},
|
||||
|
||||
RegExp: function({displayString}) {
|
||||
return VariablesView.getString(displayString, { noStringQuotes: true });
|
||||
},
|
||||
|
||||
Date: function({preview}) {
|
||||
if (!preview || !("timestamp" in preview)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof preview.timestamp != "number") {
|
||||
return new Date(preview.timestamp).toString(); // invalid date
|
||||
}
|
||||
|
||||
return "Date " + new Date(preview.timestamp).toISOString();
|
||||
},
|
||||
}; // VariablesView.stringifiers.byObjectClass
|
||||
|
||||
VariablesView.stringifiers.byObjectKind = {
|
||||
ArrayLike: function(aGrip, {concise}) {
|
||||
let {preview} = aGrip;
|
||||
if (concise) {
|
||||
return aGrip.class + "[" + preview.length + "]";
|
||||
}
|
||||
|
||||
if (!preview.items) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let shown = 0, result = [], lastHole = null;
|
||||
for (let item of preview.items) {
|
||||
if (item === null) {
|
||||
if (lastHole !== null) {
|
||||
result[lastHole] += ",";
|
||||
} else {
|
||||
result.push("");
|
||||
}
|
||||
lastHole = result.length - 1;
|
||||
} else {
|
||||
lastHole = null;
|
||||
result.push(VariablesView.getString(item, { concise: true }));
|
||||
}
|
||||
shown++;
|
||||
}
|
||||
|
||||
if (shown < preview.length) {
|
||||
let n = preview.length - shown;
|
||||
result.push(VariablesView.stringifiers._getNMoreString(n));
|
||||
} else if (lastHole !== null) {
|
||||
// make sure we have the right number of commas...
|
||||
result[lastHole] += ",";
|
||||
}
|
||||
|
||||
let prefix = aGrip.class == "Array" ? "" : aGrip.class + " ";
|
||||
return prefix + "[" + result.join(", ") + "]";
|
||||
},
|
||||
|
||||
MapLike: function(aGrip, {concise}) {
|
||||
let {preview} = aGrip;
|
||||
if (concise || !preview.entries) {
|
||||
let size = typeof preview.size == "number" ?
|
||||
"[" + preview.size + "]" : "";
|
||||
return aGrip.class + size;
|
||||
}
|
||||
|
||||
let entries = [];
|
||||
for (let [key, value] of preview.entries) {
|
||||
let keyString = VariablesView.getString(key, {
|
||||
concise: true,
|
||||
noStringQuotes: true,
|
||||
});
|
||||
let valueString = VariablesView.getString(value, { concise: true });
|
||||
entries.push(keyString + ": " + valueString);
|
||||
}
|
||||
|
||||
if (typeof preview.size == "number" && preview.size > entries.length) {
|
||||
let n = preview.size - entries.length;
|
||||
entries.push(VariablesView.stringifiers._getNMoreString(n));
|
||||
}
|
||||
|
||||
return aGrip.class + " {" + entries.join(", ") + "}";
|
||||
},
|
||||
|
||||
ObjectWithText: function(aGrip, {concise}) {
|
||||
if (concise) {
|
||||
return aGrip.class;
|
||||
}
|
||||
|
||||
return aGrip.class + " " + VariablesView.getString(aGrip.preview.text);
|
||||
},
|
||||
|
||||
ObjectWithURL: function(aGrip, {concise}) {
|
||||
let result = aGrip.class;
|
||||
let url = aGrip.preview.url;
|
||||
if (!VariablesView.isFalsy({ value: url })) {
|
||||
result += " \u2192 " + WebConsoleUtils.abbreviateSourceURL(url,
|
||||
{ onlyCropQuery: !concise });
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
// Stringifier for any kind of object.
|
||||
Object: function(aGrip, {concise}) {
|
||||
if (concise) {
|
||||
return aGrip.class;
|
||||
}
|
||||
|
||||
let {preview} = aGrip;
|
||||
let props = [];
|
||||
for (let key of Object.keys(preview.ownProperties || {})) {
|
||||
let value = preview.ownProperties[key];
|
||||
let valueString = "";
|
||||
if (value.get) {
|
||||
valueString = "Getter";
|
||||
} else if (value.set) {
|
||||
valueString = "Setter";
|
||||
} else {
|
||||
valueString = VariablesView.getString(value.value, { concise: true });
|
||||
}
|
||||
props.push(key + ": " + valueString);
|
||||
}
|
||||
|
||||
for (let key of Object.keys(preview.safeGetterValues || {})) {
|
||||
let value = preview.safeGetterValues[key];
|
||||
let valueString = VariablesView.getString(value.getterValue,
|
||||
{ concise: true });
|
||||
props.push(key + ": " + valueString);
|
||||
}
|
||||
|
||||
if (!props.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (preview.ownPropertiesLength) {
|
||||
let previewLength = Object.keys(preview.ownProperties).length;
|
||||
let diff = preview.ownPropertiesLength - previewLength;
|
||||
if (diff > 0) {
|
||||
props.push(VariablesView.stringifiers._getNMoreString(diff));
|
||||
}
|
||||
}
|
||||
|
||||
let prefix = aGrip.class != "Object" ? aGrip.class + " " : "";
|
||||
return prefix + "{" + props.join(", ") + "}";
|
||||
}, // Object
|
||||
|
||||
Error: function(aGrip, {concise}) {
|
||||
let {preview} = aGrip;
|
||||
let name = VariablesView.getString(preview.name, { noStringQuotes: true });
|
||||
if (concise) {
|
||||
return name || aGrip.class;
|
||||
}
|
||||
|
||||
let msg = name + ": " +
|
||||
VariablesView.getString(preview.message, { noStringQuotes: true });
|
||||
|
||||
if (!VariablesView.isFalsy({ value: preview.stack })) {
|
||||
msg += "\n" + STR.GetStringFromName("variablesViewErrorStacktrace") +
|
||||
"\n" + preview.stack;
|
||||
}
|
||||
|
||||
return msg;
|
||||
},
|
||||
|
||||
DOMException: function(aGrip, {concise}) {
|
||||
let {preview} = aGrip;
|
||||
if (concise) {
|
||||
return preview.name || aGrip.class;
|
||||
}
|
||||
|
||||
let msg = aGrip.class + " [" + preview.name + ": " +
|
||||
VariablesView.getString(preview.message) + "\n" +
|
||||
"code: " + preview.code + "\n" +
|
||||
"nsresult: 0x" + (+preview.result).toString(16);
|
||||
|
||||
if (preview.filename) {
|
||||
msg += "\nlocation: " + preview.filename;
|
||||
if (preview.lineNumber) {
|
||||
msg += ":" + preview.lineNumber;
|
||||
}
|
||||
}
|
||||
|
||||
return msg + "]";
|
||||
},
|
||||
|
||||
DOMEvent: function(aGrip, {concise}) {
|
||||
let {preview} = aGrip;
|
||||
if (!preview.type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (concise) {
|
||||
return aGrip.class + " " + preview.type;
|
||||
}
|
||||
|
||||
let result = preview.type;
|
||||
|
||||
if (preview.eventKind == "key" && preview.modifiers &&
|
||||
preview.modifiers.length) {
|
||||
result += " " + preview.modifiers.join("-");
|
||||
}
|
||||
|
||||
let props = [];
|
||||
if (preview.target) {
|
||||
let target = VariablesView.getString(preview.target, { concise: true });
|
||||
props.push("target: " + target);
|
||||
}
|
||||
|
||||
for (let prop in preview.properties) {
|
||||
let value = preview.properties[prop];
|
||||
props.push(prop + ": " + VariablesView.getString(value, { concise: true }));
|
||||
}
|
||||
|
||||
return result + " {" + props.join(", ") + "}";
|
||||
}, // DOMEvent
|
||||
|
||||
DOMNode: function(aGrip, {concise}) {
|
||||
let {preview} = aGrip;
|
||||
|
||||
switch (preview.nodeType) {
|
||||
case Ci.nsIDOMNode.DOCUMENT_NODE: {
|
||||
let location = WebConsoleUtils.abbreviateSourceURL(preview.location,
|
||||
{ onlyCropQuery: !concise });
|
||||
return aGrip.class + " \u2192 " + location;
|
||||
}
|
||||
|
||||
case Ci.nsIDOMNode.ATTRIBUTE_NODE: {
|
||||
let value = VariablesView.getString(preview.value, { noStringQuotes: true });
|
||||
return preview.nodeName + '="' + escapeHTML(value) + '"';
|
||||
}
|
||||
|
||||
case Ci.nsIDOMNode.TEXT_NODE:
|
||||
return preview.nodeName + " " +
|
||||
VariablesView.getString(preview.textContent);
|
||||
|
||||
case Ci.nsIDOMNode.COMMENT_NODE: {
|
||||
let comment = VariablesView.getString(preview.textContent,
|
||||
{ noStringQuotes: true });
|
||||
return "<!--" + comment + "-->";
|
||||
}
|
||||
|
||||
case Ci.nsIDOMNode.DOCUMENT_FRAGMENT_NODE: {
|
||||
if (concise || !preview.childNodes) {
|
||||
return aGrip.class + "[" + preview.childNodesLength + "]";
|
||||
}
|
||||
let nodes = [];
|
||||
for (let node of preview.childNodes) {
|
||||
nodes.push(VariablesView.getString(node));
|
||||
}
|
||||
if (nodes.length < preview.childNodesLength) {
|
||||
let n = preview.childNodesLength - nodes.length;
|
||||
nodes.push(VariablesView.stringifiers._getNMoreString(n));
|
||||
}
|
||||
return aGrip.class + " [" + nodes.join(", ") + "]";
|
||||
}
|
||||
|
||||
case Ci.nsIDOMNode.ELEMENT_NODE: {
|
||||
let attrs = preview.attributes;
|
||||
if (!concise) {
|
||||
let n = 0, result = "<" + preview.nodeName;
|
||||
for (let name in attrs) {
|
||||
let value = VariablesView.getString(attrs[name],
|
||||
{ noStringQuotes: true });
|
||||
result += " " + name + '="' + escapeHTML(value) + '"';
|
||||
n++;
|
||||
}
|
||||
if (preview.attributesLength > n) {
|
||||
result += " " + Scope.ellipsis;
|
||||
}
|
||||
return result + ">";
|
||||
}
|
||||
|
||||
let result = "<" + preview.nodeName;
|
||||
if (attrs.id) {
|
||||
result += "#" + attrs.id;
|
||||
}
|
||||
return result + ">";
|
||||
}
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}, // DOMNode
|
||||
}; // VariablesView.stringifiers.byObjectKind
|
||||
|
||||
|
||||
/**
|
||||
* Get the "N more…" formatted string, given an N. This is used for displaying
|
||||
* how many elements are not displayed in an object preview (eg. an array).
|
||||
*
|
||||
* @private
|
||||
* @param number aNumber
|
||||
* @return string
|
||||
*/
|
||||
VariablesView.stringifiers._getNMoreString = function(aNumber) {
|
||||
let str = STR.GetStringFromName("variablesViewMoreObjects");
|
||||
return PluralForm.get(aNumber, str).replace("#1", aNumber);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a custom class style for a grip.
|
||||
*
|
||||
@ -3208,6 +3591,22 @@ let generateId = (function() {
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Escape some HTML special characters. We do not need full HTML serialization
|
||||
* here, we just want to make strings safe to display in HTML attributes, for
|
||||
* the stringifiers.
|
||||
*
|
||||
* @param string aString
|
||||
* @return string
|
||||
*/
|
||||
function escapeHTML(aString) {
|
||||
return aString.replace(/&/g, "&")
|
||||
.replace(/"/g, """)
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An Editable encapsulates the UI of an edit box that overlays a label,
|
||||
* allowing the user to edit the value.
|
||||
|
@ -997,10 +997,12 @@ Messages.Extended.prototype = Heritage.extend(Messages.Simple.prototype,
|
||||
}
|
||||
|
||||
let result = this.document.createDocumentFragment();
|
||||
if (!isPrimitive || (!this._quoteStrings && typeof piece == "string")) {
|
||||
result.textContent = piece;
|
||||
if (isPrimitive) {
|
||||
result.textContent = VariablesView.getString(piece, {
|
||||
noStringQuotes: !this._quoteStrings,
|
||||
});
|
||||
} else {
|
||||
result.textContent = VariablesView.getString(piece);
|
||||
result.textContent = piece;
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -1219,7 +1221,7 @@ Widgets.JSObject.prototype = Heritage.extend(Widgets.BaseWidget.prototype,
|
||||
_onClick: function()
|
||||
{
|
||||
this.output.openVariablesView({
|
||||
label: this.element.textContent,
|
||||
label: VariablesView.getString(this.objectActor, { concise: true }),
|
||||
objectActor: this.objectActor,
|
||||
autofocus: true,
|
||||
});
|
||||
@ -1273,11 +1275,10 @@ Widgets.LongString.prototype = Heritage.extend(Widgets.BaseWidget.prototype,
|
||||
*/
|
||||
_renderString: function(str)
|
||||
{
|
||||
if (this.message._quoteStrings) {
|
||||
this.element.textContent = VariablesView.getString(str);
|
||||
} else {
|
||||
this.element.textContent = str;
|
||||
}
|
||||
this.element.textContent = VariablesView.getString(str, {
|
||||
noStringQuotes: !this.message._quoteStrings,
|
||||
noEllipsis: true,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -64,6 +64,10 @@ support-files =
|
||||
test-console-extras.html
|
||||
test-console-replaced-api.html
|
||||
test-console.html
|
||||
test-console-output-02.html
|
||||
test-console-output-03.html
|
||||
test-console-output-04.html
|
||||
test-console-output-events.html
|
||||
test-consoleiframes.html
|
||||
test-data.json
|
||||
test-data.json^headers^
|
||||
@ -167,7 +171,6 @@ support-files =
|
||||
[browser_webconsole_bug_597136_network_requests_from_chrome.js]
|
||||
[browser_webconsole_bug_597460_filter_scroll.js]
|
||||
[browser_webconsole_bug_597756_reopen_closed_tab.js]
|
||||
[browser_webconsole_bug_598357_jsterm_output.js]
|
||||
[browser_webconsole_bug_599725_response_headers.js]
|
||||
[browser_webconsole_bug_600183_charset.js]
|
||||
[browser_webconsole_bug_601177_log_levels.js]
|
||||
@ -248,3 +251,8 @@ run-if = os == "mac"
|
||||
[browser_webconsole_expandable_timestamps.js]
|
||||
[browser_webconsole_autocomplete_in_debugger_stackframe.js]
|
||||
[browser_webconsole_autocomplete_popup_close_on_tab_switch.js]
|
||||
[browser_webconsole_output_01.js]
|
||||
[browser_webconsole_output_02.js]
|
||||
[browser_webconsole_output_03.js]
|
||||
[browser_webconsole_output_04.js]
|
||||
[browser_webconsole_output_events.js]
|
||||
|
@ -36,7 +36,8 @@ function onExecuteFooObj(msg)
|
||||
|
||||
let anchor = msg.querySelector("a");
|
||||
ok(anchor, "object anchor");
|
||||
isnot(anchor.textContent.indexOf("[object Object]"), -1, "message text check");
|
||||
isnot(anchor.textContent.indexOf('testProp: "testValue"'), -1,
|
||||
"message text check");
|
||||
|
||||
gJSTerm.once("variablesview-fetched", onFooObjFetch);
|
||||
EventUtils.synthesizeMouse(anchor, 2, 2, {}, gWebConsole.iframeWindow)
|
||||
@ -76,7 +77,8 @@ function onExecuteWindow(msg)
|
||||
ok(msg, "output message found");
|
||||
let anchor = msg.querySelector("a");
|
||||
ok(anchor, "object anchor");
|
||||
isnot(anchor.textContent.indexOf("[object Window]"), -1, "message text check");
|
||||
isnot(anchor.textContent.indexOf("Window \u2192 http://example.com/browser/"), -1,
|
||||
"message text check");
|
||||
|
||||
gJSTerm.once("variablesview-fetched", onWindowFetch);
|
||||
EventUtils.synthesizeMouse(anchor, 2, 2, {}, gWebConsole.iframeWindow)
|
||||
|
@ -46,7 +46,7 @@ function onConsoleMessage(aResults)
|
||||
{
|
||||
let clickable = aResults[0].clickableElements[0];
|
||||
ok(clickable, "clickable object found");
|
||||
isnot(clickable.textContent.indexOf("[object Object]"), -1,
|
||||
isnot(clickable.textContent.indexOf('{hello: "world!",'), -1,
|
||||
"message text check");
|
||||
|
||||
gJSTerm.once("variablesview-fetched", onObjFetch);
|
||||
|
@ -71,7 +71,7 @@ function test()
|
||||
},
|
||||
{
|
||||
name: "console.error output",
|
||||
text: /\bbug851231-error\b.+\[object Object\]/,
|
||||
text: /\bbug851231-error\b.+\{bug851231prop:\s"bug851231value"\}/,
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_ERROR,
|
||||
objects: true,
|
||||
@ -91,7 +91,7 @@ function test()
|
||||
},
|
||||
{
|
||||
name: "console.dir output",
|
||||
consoleDir: "[object XULDocument]",
|
||||
consoleDir: "XULDocument {",
|
||||
},
|
||||
{
|
||||
name: "console.time output",
|
||||
|
@ -34,7 +34,7 @@ function performTest(hud)
|
||||
}).then(([result]) => {
|
||||
let clickable = result.clickableElements[0];
|
||||
ok(clickable, "the console.log() object anchor was found");
|
||||
isnot(clickable.textContent.indexOf("Object"), -1,
|
||||
isnot(clickable.textContent.indexOf('{abba: "omgBug676722"}'), -1,
|
||||
"clickable node content is correct");
|
||||
|
||||
hud.jsterm.once("variablesview-fetched",
|
||||
|
@ -30,7 +30,7 @@ function consoleOpened(hud)
|
||||
waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
text: "[object HTMLDocument]",
|
||||
text: "HTMLDocument \u2192 data:text/html;charset=utf8",
|
||||
category: CATEGORY_OUTPUT,
|
||||
objects: true,
|
||||
}],
|
||||
@ -90,7 +90,7 @@ function testParagraphs()
|
||||
waitForMessages({
|
||||
webconsole: gWebConsole,
|
||||
messages: [{
|
||||
text: "[object NodeList]",
|
||||
text: "NodeList [",
|
||||
category: CATEGORY_OUTPUT,
|
||||
objects: true,
|
||||
}],
|
||||
|
@ -28,7 +28,8 @@ function consoleOpened(hud)
|
||||
function onExecuteFooObj(msg)
|
||||
{
|
||||
ok(msg, "output message found");
|
||||
isnot(msg.textContent.indexOf("[object Object]"), -1, "message text check");
|
||||
isnot(msg.textContent.indexOf('{testProp: "testValue"}'), -1,
|
||||
"message text check");
|
||||
|
||||
let anchor = msg.querySelector("a");
|
||||
ok(anchor, "object link found");
|
||||
|
@ -62,7 +62,8 @@ function onFramesAdded()
|
||||
function onExecuteFooObj(msg)
|
||||
{
|
||||
ok(msg, "output message found");
|
||||
isnot(msg.textContent.indexOf("[object Object]"), -1, "message text check");
|
||||
isnot(msg.textContent.indexOf('{testProp2: "testValue2"}'), -1,
|
||||
"message text check");
|
||||
|
||||
let anchor = msg.querySelector("a");
|
||||
ok(anchor, "object link found");
|
||||
|
@ -57,7 +57,8 @@ function onFramesAdded()
|
||||
function onExecuteFooObj(msg)
|
||||
{
|
||||
ok(msg, "output message found");
|
||||
isnot(msg.textContent.indexOf("[object Object]"), -1, "message text check");
|
||||
isnot(msg.textContent.indexOf('{testProp2: "testValue2"}'), -1,
|
||||
"message text check");
|
||||
|
||||
let anchor = msg.querySelector("a");
|
||||
ok(anchor, "object link found");
|
||||
|
@ -29,7 +29,7 @@ function test()
|
||||
|
||||
findVariableViewProperties(aVar, [
|
||||
{ name: "testProp", value: "testValue" },
|
||||
{ name: "document", value: "HTMLDocument" },
|
||||
{ name: "document", value: /HTMLDocument \u2192 data:/ },
|
||||
], { webconsole: hud }).then(finishTest);
|
||||
}
|
||||
}
|
||||
|
@ -28,10 +28,10 @@ function performTest(hud)
|
||||
ok(!hud.outputNode.querySelector("#foobar"), "no #foobar element found");
|
||||
|
||||
ok(msg, "eval output node found");
|
||||
is(msg.textContent.indexOf("HTMLDivElement"), -1,
|
||||
"HTMLDivElement string is not displayed");
|
||||
isnot(msg.textContent.indexOf("HTMLParagraphElement"), -1,
|
||||
"HTMLParagraphElement string is displayed");
|
||||
is(msg.textContent.indexOf("<div>"), -1,
|
||||
"<div> string is not displayed");
|
||||
isnot(msg.textContent.indexOf("<p>"), -1,
|
||||
"<p> string is displayed");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(msg, {type: "mousemove"});
|
||||
ok(!gBrowser._bug772506, "no content variable");
|
||||
|
@ -80,9 +80,8 @@ function tab2Loaded(aEvent) {
|
||||
function testEnd() {
|
||||
ok(noErrors, "there were no errors");
|
||||
|
||||
Array.forEach(win1.gBrowser.tabs, function(aTab) {
|
||||
win1.gBrowser.removeTab(aTab);
|
||||
});
|
||||
win1.gBrowser.removeTab(tab1);
|
||||
|
||||
Array.forEach(win2.gBrowser.tabs, function(aTab) {
|
||||
win2.gBrowser.removeTab(aTab);
|
||||
});
|
||||
|
@ -1,267 +0,0 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mihai Șucan <mihai.sucan@gmail.com>
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
|
||||
|
||||
let testEnded = false;
|
||||
let pos = -1;
|
||||
|
||||
let dateNow = Date.now();
|
||||
|
||||
let tempScope = {};
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm", tempScope);
|
||||
|
||||
let longString = (new Array(tempScope.DebuggerServer.LONG_STRING_LENGTH + 4)).join("a");
|
||||
let initialString = longString.substring(0,
|
||||
tempScope.DebuggerServer.LONG_STRING_INITIAL_LENGTH);
|
||||
|
||||
let inputValues = [
|
||||
// [showsVariablesView?, input value, expected output format,
|
||||
// print() output, console API output, optional console API test]
|
||||
|
||||
// 0
|
||||
[false, "'hello \\nfrom \\rthe \\\"string world!'",
|
||||
'"hello \nfrom \rthe "string world!"',
|
||||
"hello \nfrom \rthe \"string world!"],
|
||||
|
||||
// 1
|
||||
[false, "'\xFA\u1E47\u0129\xE7\xF6d\xEA \u021B\u0115\u0219\u0165'",
|
||||
"\"\xFA\u1E47\u0129\xE7\xF6d\xEA \u021B\u0115\u0219\u0165\"",
|
||||
"\xFA\u1E47\u0129\xE7\xF6d\xEA \u021B\u0115\u0219\u0165"],
|
||||
|
||||
// 2
|
||||
[false, "window.location.href", '"' + TEST_URI + '"', TEST_URI],
|
||||
|
||||
// 3
|
||||
[false, "0", "0"],
|
||||
|
||||
// 4
|
||||
[false, "'0'", '"0"', "0"],
|
||||
|
||||
// 5
|
||||
[false, "42", "42"],
|
||||
|
||||
// 6
|
||||
[false, "'42'", '"42"', "42"],
|
||||
|
||||
// 7
|
||||
[true, "/foobar/", "[object RegExp]", '"/foobar/"', "[object RegExp]"],
|
||||
|
||||
// 8
|
||||
[false, "null", "null"],
|
||||
|
||||
// 9
|
||||
[false, "undefined", "undefined"],
|
||||
|
||||
// 10
|
||||
[false, "true", "true"],
|
||||
|
||||
// 11
|
||||
[true, "document.getElementById", "[object Function]",
|
||||
"function getElementById() {\n [native code]\n}",
|
||||
"[object Function]"],
|
||||
|
||||
// 12
|
||||
[true, "(function() { return 42; })", "[object Function]",
|
||||
"function () { return 42; }", "[object Function]"],
|
||||
|
||||
// 13
|
||||
[true, "new Date(" + dateNow + ")", "[object Date]", (new Date(dateNow)).toString(), "[object Date]"],
|
||||
|
||||
// 14
|
||||
[true, "document.body", "[object HTMLBodyElement]"],
|
||||
|
||||
// 15
|
||||
[true, "window.location", "[object Location]", TEST_URI, "[object Location]"],
|
||||
|
||||
// 16
|
||||
[true, "[1,2,3,'a','b','c','4','5']", '[object Array]',
|
||||
'1,2,3,a,b,c,4,5',
|
||||
"[object Array]"],
|
||||
|
||||
// 17
|
||||
[true, "({a:'b', c:'d', e:1, f:'2'})", "[object Object]"],
|
||||
|
||||
// 18
|
||||
[false, "'" + longString + "'",
|
||||
'"' + initialString + "\"[\u2026]", initialString],
|
||||
];
|
||||
|
||||
longString = null;
|
||||
initialString = null;
|
||||
tempScope = null;
|
||||
|
||||
let eventHandlers = [];
|
||||
let popupShown = [];
|
||||
let HUD;
|
||||
let testDriver;
|
||||
|
||||
function tabLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, tabLoad, true);
|
||||
|
||||
waitForFocus(function () {
|
||||
openConsole(null, function(aHud) {
|
||||
HUD = aHud;
|
||||
testNext();
|
||||
});
|
||||
}, content);
|
||||
}
|
||||
|
||||
function subtestNext() {
|
||||
testDriver.next();
|
||||
}
|
||||
|
||||
function testNext() {
|
||||
pos++;
|
||||
if (pos == inputValues.length) {
|
||||
testEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
testDriver = testGen();
|
||||
testDriver.next();
|
||||
}
|
||||
|
||||
function testGen() {
|
||||
let cpos = pos;
|
||||
|
||||
let showsVariablesView = inputValues[cpos][0];
|
||||
let inputValue = inputValues[cpos][1];
|
||||
let expectedOutput = inputValues[cpos][2];
|
||||
|
||||
let printOutput = inputValues[cpos].length >= 4 ?
|
||||
inputValues[cpos][3] : expectedOutput;
|
||||
|
||||
let consoleOutput = inputValues[cpos].length >= 5 ?
|
||||
inputValues[cpos][4] : printOutput;
|
||||
|
||||
let consoleTest = inputValues[cpos][5] || inputValue;
|
||||
|
||||
HUD.jsterm.clearOutput();
|
||||
|
||||
// Test the console.log() output.
|
||||
|
||||
let outputItem;
|
||||
function onExecute(msg) {
|
||||
outputItem = msg;
|
||||
subtestNext();
|
||||
}
|
||||
|
||||
HUD.jsterm.execute("console.log(" + consoleTest + ")");
|
||||
|
||||
waitForMessages({
|
||||
webconsole: HUD,
|
||||
messages: [{
|
||||
name: "console API output is correct for inputValues[" + cpos + "]",
|
||||
text: consoleOutput,
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
}],
|
||||
}).then(subtestNext);
|
||||
|
||||
yield undefined;
|
||||
|
||||
HUD.jsterm.clearOutput();
|
||||
|
||||
// Test jsterm print() output.
|
||||
|
||||
HUD.jsterm.setInputValue("print(" + inputValue + ")");
|
||||
HUD.jsterm.execute(null, onExecute);
|
||||
|
||||
yield undefined;
|
||||
|
||||
ok(outputItem,
|
||||
"found the jsterm print() output line for inputValues[" + cpos + "]");
|
||||
ok(outputItem.textContent.indexOf(printOutput) > -1,
|
||||
"jsterm print() output is correct for inputValues[" + cpos + "]");
|
||||
|
||||
// Test jsterm execution output.
|
||||
|
||||
HUD.jsterm.clearOutput();
|
||||
HUD.jsterm.setInputValue(inputValue);
|
||||
HUD.jsterm.execute(null, onExecute);
|
||||
|
||||
yield undefined;
|
||||
|
||||
ok(outputItem, "found the jsterm output line for inputValues[" + cpos + "]");
|
||||
ok(outputItem.textContent.indexOf(expectedOutput) > -1,
|
||||
"jsterm output is correct for inputValues[" + cpos + "]");
|
||||
|
||||
let messageBody = outputItem.querySelector(".body a") ||
|
||||
outputItem.querySelector(".body");
|
||||
ok(messageBody, "we have the message body for inputValues[" + cpos + "]");
|
||||
|
||||
// Test click on output.
|
||||
let eventHandlerID = eventHandlers.length + 1;
|
||||
|
||||
let variablesViewShown = function(aEvent, aView, aOptions) {
|
||||
if (aOptions.label.indexOf(expectedOutput) == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
HUD.jsterm.off("variablesview-open", variablesViewShown);
|
||||
|
||||
eventHandlers[eventHandlerID] = null;
|
||||
|
||||
ok(showsVariablesView,
|
||||
"the variables view shown for inputValues[" + cpos + "]");
|
||||
|
||||
popupShown[cpos] = true;
|
||||
|
||||
if (showsVariablesView) {
|
||||
executeSoon(subtestNext);
|
||||
}
|
||||
};
|
||||
|
||||
HUD.jsterm.on("variablesview-open", variablesViewShown);
|
||||
|
||||
eventHandlers.push(variablesViewShown);
|
||||
|
||||
EventUtils.synthesizeMouse(messageBody, 2, 2, {}, HUD.iframeWindow);
|
||||
|
||||
if (showsVariablesView) {
|
||||
info("messageBody tagName '" + messageBody.tagName + "' className '" + messageBody.className + "'");
|
||||
yield undefined; // wait for the panel to open if we need to.
|
||||
}
|
||||
|
||||
testNext();
|
||||
|
||||
yield undefined;
|
||||
}
|
||||
|
||||
function testEnd() {
|
||||
if (testEnded) {
|
||||
return;
|
||||
}
|
||||
|
||||
testEnded = true;
|
||||
|
||||
for (let i = 0; i < eventHandlers.length; i++) {
|
||||
if (eventHandlers[i]) {
|
||||
HUD.jsterm.off("variablesview-open", eventHandlers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < inputValues.length; i++) {
|
||||
if (inputValues[i][0] && !popupShown[i]) {
|
||||
ok(false, "the variables view failed to show for inputValues[" + i + "]");
|
||||
}
|
||||
}
|
||||
|
||||
HUD = inputValues = testDriver = null;
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
|
||||
function test() {
|
||||
requestLongerTimeout(2);
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("load", tabLoad, true);
|
||||
}
|
||||
|
@ -57,20 +57,16 @@ function autocompletePopupHidden()
|
||||
popup._panel.removeEventListener("popuphidden", autocompletePopupHidden, false);
|
||||
|
||||
ok(!popup.isOpen, "popup is not open");
|
||||
|
||||
jsterm.once("autocomplete-updated", function() {
|
||||
is(completeNode.value, testStr + "dy", "autocomplete shows document.body");
|
||||
testPropertyPanel();
|
||||
});
|
||||
|
||||
let inputStr = "document.b";
|
||||
jsterm.setInputValue(inputStr);
|
||||
EventUtils.synthesizeKey("o", {});
|
||||
let testStr = inputStr.replace(/./g, " ") + " ";
|
||||
|
||||
waitForSuccess({
|
||||
name: "autocomplete shows document.body",
|
||||
validatorFn: function()
|
||||
{
|
||||
return completeNode.value == testStr + "dy";
|
||||
},
|
||||
successFn: testPropertyPanel,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
}
|
||||
|
||||
function testPropertyPanel()
|
||||
@ -87,7 +83,6 @@ function testPropertyPanel()
|
||||
function onVariablesViewReady(aEvent, aView)
|
||||
{
|
||||
findVariableViewProperties(aView, [
|
||||
{ name: "body", value: "HTMLBodyElement" },
|
||||
{ name: "body", value: "<body>" },
|
||||
], { webconsole: gHUD }).then(finishTest);
|
||||
}
|
||||
|
||||
|
@ -88,8 +88,7 @@ function performWebConsoleTests(hud)
|
||||
|
||||
function onNodeOutput(node)
|
||||
{
|
||||
isnot(node.textContent.indexOf("[object HTMLHeadingElement"), -1,
|
||||
"correct output for $0");
|
||||
isnot(node.textContent.indexOf("<h1>"), -1, "correct output for $0");
|
||||
|
||||
jsterm.clearOutput();
|
||||
jsterm.execute("$0.textContent = 'bug653531'", onNodeUpdate);
|
||||
|
@ -22,8 +22,8 @@ function consoleOpened(hud) {
|
||||
|
||||
function testConsoleDir(hud, ev, view) {
|
||||
findVariableViewProperties(view, [
|
||||
{ name: "__proto__.__proto__.querySelectorAll", value: "Function" },
|
||||
{ name: "location", value: "Location" },
|
||||
{ name: "__proto__.write", value: "Function" },
|
||||
{ name: "__proto__.__proto__.querySelectorAll", value: "querySelectorAll()" },
|
||||
{ name: "location", value: /Location \u2192 data:Web/ },
|
||||
{ name: "__proto__.write", value: "write()" },
|
||||
], { webconsole: hud }).then(finishTest);
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ function consoleOpened(hud)
|
||||
waitForMessages({
|
||||
webconsole: gWebConsole,
|
||||
messages: [{
|
||||
text: "[object Function]",
|
||||
text: "function _pfactory/<.getName()",
|
||||
category: CATEGORY_OUTPUT,
|
||||
objects: true,
|
||||
}],
|
||||
|
@ -118,7 +118,7 @@ function testJSTerm(hud)
|
||||
|
||||
jsterm.clearOutput();
|
||||
jsterm.execute("pprint({b:2, a:1})");
|
||||
checkResult('" b: 2\n a: 1"', "pprint()");
|
||||
checkResult("\" b: 2\\n a: 1\"", "pprint()");
|
||||
yield undefined;
|
||||
|
||||
// check instanceof correctness, bug 599940
|
||||
@ -154,7 +154,7 @@ function testJSTerm(hud)
|
||||
// bug 614561
|
||||
jsterm.clearOutput();
|
||||
jsterm.execute("pprint('hi')");
|
||||
checkResult('" 0: "h"\n 1: "i""', "pprint('hi')");
|
||||
checkResult("\" 0: \\\"h\\\"\\n 1: \\\"i\\\"\"", "pprint('hi')");
|
||||
yield undefined;
|
||||
|
||||
// check that pprint(function) shows function source, bug 618344
|
||||
|
146
browser/devtools/webconsole/test/browser_webconsole_output_01.js
Normal file
146
browser/devtools/webconsole/test/browser_webconsole_output_01.js
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Test the webconsole output for various types of objects.
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf8,test for console output - 01";
|
||||
|
||||
let dateNow = Date.now();
|
||||
let {DebuggerServer} = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
|
||||
|
||||
let LONG_STRING_LENGTH = DebuggerServer.LONG_STRING_LENGTH;
|
||||
let LONG_STRING_INITIAL_LENGTH = DebuggerServer.LONG_STRING_INITIAL_LENGTH;
|
||||
DebuggerServer.LONG_STRING_LENGTH = 100;
|
||||
DebuggerServer.LONG_STRING_INITIAL_LENGTH = 50;
|
||||
|
||||
let longString = (new Array(DebuggerServer.LONG_STRING_LENGTH + 4)).join("a");
|
||||
let initialString = longString.substring(0, DebuggerServer.LONG_STRING_INITIAL_LENGTH);
|
||||
|
||||
let inputTests = [
|
||||
// 0
|
||||
{
|
||||
input: "'hello \\nfrom \\rthe \\\"string world!'",
|
||||
output: "\"hello \\nfrom \\rthe \\\"string world!\"",
|
||||
},
|
||||
|
||||
// 1
|
||||
{
|
||||
// unicode test
|
||||
input: "'\xFA\u1E47\u0129\xE7\xF6d\xEA \u021B\u0115\u0219\u0165'",
|
||||
output: "\"\\xFA\\u1E47\\u0129\\xE7\\xF6d\\xEA \\u021B\\u0115\\u0219\\u0165\"",
|
||||
},
|
||||
|
||||
// 2
|
||||
{
|
||||
input: "'" + longString + "'",
|
||||
output: '"' + initialString + "\"[\u2026]",
|
||||
printOutput: initialString,
|
||||
},
|
||||
|
||||
// 3
|
||||
{
|
||||
input: "''",
|
||||
output: '""',
|
||||
printOutput: '""',
|
||||
},
|
||||
|
||||
// 4
|
||||
{
|
||||
input: "0",
|
||||
output: "0",
|
||||
},
|
||||
|
||||
// 5
|
||||
{
|
||||
input: "'0'",
|
||||
output: '"0"',
|
||||
},
|
||||
|
||||
// 6
|
||||
{
|
||||
input: "42",
|
||||
output: "42",
|
||||
},
|
||||
|
||||
// 7
|
||||
{
|
||||
input: "'42'",
|
||||
output: '"42"',
|
||||
},
|
||||
|
||||
// 8
|
||||
{
|
||||
input: "/foobar/",
|
||||
output: "/foobar/",
|
||||
inspectable: true,
|
||||
},
|
||||
|
||||
// 9
|
||||
{
|
||||
input: "/foo?b*\\s\"ar/igym",
|
||||
output: "/foo?b*\\s\"ar/gimy",
|
||||
printOutput: "/foo?b*\\\\s\\\"ar/gimy",
|
||||
inspectable: true,
|
||||
},
|
||||
|
||||
// 10
|
||||
{
|
||||
input: "null",
|
||||
output: "null",
|
||||
},
|
||||
|
||||
// 11
|
||||
{
|
||||
input: "undefined",
|
||||
output: "undefined",
|
||||
},
|
||||
|
||||
// 12
|
||||
{
|
||||
input: "true",
|
||||
output: "true",
|
||||
},
|
||||
|
||||
// 13
|
||||
{
|
||||
input: "false",
|
||||
output: "false",
|
||||
},
|
||||
|
||||
|
||||
// 14
|
||||
{
|
||||
input: "new Date(" + dateNow + ")",
|
||||
output: "Date " + (new Date(dateNow)).toISOString(),
|
||||
printOutput: (new Date(dateNow)).toString(),
|
||||
inspectable: true,
|
||||
},
|
||||
|
||||
// 15
|
||||
{
|
||||
input: "new Date('test')",
|
||||
output: "Invalid Date",
|
||||
printOutput: "Invalid Date",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "Invalid Date",
|
||||
},
|
||||
];
|
||||
|
||||
longString = initialString = null;
|
||||
|
||||
function test() {
|
||||
registerCleanupFunction(() => {
|
||||
DebuggerServer.LONG_STRING_LENGTH = LONG_STRING_LENGTH;
|
||||
DebuggerServer.LONG_STRING_INITIAL_LENGTH = LONG_STRING_INITIAL_LENGTH;
|
||||
});
|
||||
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole().then((hud) => {
|
||||
return checkOutputForInputs(hud, inputTests);
|
||||
}).then(finishTest);
|
||||
}, true);
|
||||
}
|
161
browser/devtools/webconsole/test/browser_webconsole_output_02.js
Normal file
161
browser/devtools/webconsole/test/browser_webconsole_output_02.js
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Test the webconsole output for various types of objects.
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console-output-02.html";
|
||||
|
||||
let inputTests = [
|
||||
// 0 - native named function
|
||||
{
|
||||
input: "document.getElementById",
|
||||
output: "function getElementById()",
|
||||
printOutput: "function getElementById() {\\n [native code]\\n}",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "getElementById()",
|
||||
},
|
||||
|
||||
// 1 - anonymous function
|
||||
{
|
||||
input: "(function() { return 42; })",
|
||||
output: "function ()",
|
||||
printOutput: "function () { return 42; }",
|
||||
inspectable: true,
|
||||
},
|
||||
|
||||
// 2 - named function
|
||||
{
|
||||
input: "window.testfn1",
|
||||
output: "function testfn1()",
|
||||
printOutput: "function testfn1() { return 42; }",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "testfn1()",
|
||||
},
|
||||
|
||||
// 3 - anonymous function, but spidermonkey gives us an inferred name.
|
||||
{
|
||||
input: "testobj1.testfn2",
|
||||
output: "function testobj1.testfn2()",
|
||||
printOutput: "function () { return 42; }",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "testobj1.testfn2()",
|
||||
},
|
||||
|
||||
// 4 - named function with custom display name
|
||||
{
|
||||
input: "window.testfn3",
|
||||
output: "function testfn3DisplayName()",
|
||||
printOutput: "function testfn3() { return 42; }",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "testfn3DisplayName()",
|
||||
},
|
||||
|
||||
// 5 - basic array
|
||||
{
|
||||
input: "window.array1",
|
||||
output: '[1, 2, 3, "a", "b", "c", "4", "5"]',
|
||||
printOutput: "1,2,3,a,b,c,4,5",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "Array[8]",
|
||||
},
|
||||
|
||||
// 6 - array with objects
|
||||
{
|
||||
input: "window.array2",
|
||||
output: '["a", HTMLDocument \u2192 test-console-output-02.html, <body>, ' +
|
||||
"DOMStringMap[0], DOMTokenList[0]]",
|
||||
printOutput: '"a,[object HTMLDocument],[object HTMLBodyElement],' +
|
||||
'[object DOMStringMap],"',
|
||||
inspectable: true,
|
||||
variablesViewLabel: "Array[5]",
|
||||
},
|
||||
|
||||
// 7 - array with more than 10 elements
|
||||
{
|
||||
input: "window.array3",
|
||||
output: '[1, Window \u2192 test-console-output-02.html, null, "a", "b", ' +
|
||||
'undefined, false, "", -Infinity, testfn3DisplayName(), 3 more\u2026]',
|
||||
printOutput: '"1,[object Window],,a,b,,false,,-Infinity,' +
|
||||
'function testfn3() { return 42; },[object Object],foo,bar"',
|
||||
inspectable: true,
|
||||
variablesViewLabel: "Array[13]",
|
||||
},
|
||||
|
||||
// 8 - array with holes and a cyclic reference
|
||||
{
|
||||
input: "window.array4",
|
||||
output: '[,,,,, "test", Array[7]]',
|
||||
printOutput: '",,,,,test,"',
|
||||
inspectable: true,
|
||||
variablesViewLabel: "Array[7]",
|
||||
},
|
||||
|
||||
// 9
|
||||
{
|
||||
input: "window.typedarray1",
|
||||
output: 'Int32Array [1, 287, 8651, 40983, 8754]',
|
||||
printOutput: "[object Int32Array]",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "Int32Array[5]",
|
||||
},
|
||||
|
||||
// 10 - Set with cyclic reference
|
||||
{
|
||||
input: "window.set1",
|
||||
output: 'Set [1, 2, null, Array[13], "a", "b", undefined, <head>, Set[9]]',
|
||||
printOutput: "[object Set]",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "Set[9]",
|
||||
},
|
||||
|
||||
// 11 - Object with cyclic reference and a getter
|
||||
{
|
||||
input: "window.testobj2",
|
||||
output: '{a: "b", c: "d", e: 1, f: "2", foo: Object, bar: Object, ' +
|
||||
"getterTest: Getter}",
|
||||
printOutput: "[object Object]",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "Object",
|
||||
},
|
||||
|
||||
// 12 - Object with more than 10 properties
|
||||
{
|
||||
input: "window.testobj3",
|
||||
output: '{a: "b", c: "d", e: 1, f: "2", g: true, h: null, i: undefined, ' +
|
||||
'j: "", k: StyleSheetList[0], l: NodeList[5], 2 more\u2026}',
|
||||
printOutput: "[object Object]",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "Object",
|
||||
},
|
||||
|
||||
// 13 - Object with a non-enumerable property that we do not show
|
||||
{
|
||||
input: "window.testobj4",
|
||||
output: '{a: "b", c: "d", 1 more\u2026}',
|
||||
printOutput: "[object Object]",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "Object",
|
||||
},
|
||||
|
||||
// 14 - Map with cyclic references
|
||||
{
|
||||
input: "window.map1",
|
||||
output: 'Map {a: "b", HTMLCollection[2]: Object, Map[3]: Set[9]}',
|
||||
printOutput: "[object Map]",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "Map[3]",
|
||||
},
|
||||
];
|
||||
|
||||
function test() {
|
||||
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole().then((hud) => {
|
||||
return checkOutputForInputs(hud, inputTests);
|
||||
}).then(finishTest);
|
||||
}, true);
|
||||
}
|
164
browser/devtools/webconsole/test/browser_webconsole_output_03.js
Normal file
164
browser/devtools/webconsole/test/browser_webconsole_output_03.js
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Test the webconsole output for various types of objects.
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console-output-03.html";
|
||||
|
||||
let inputTests = [
|
||||
// 0
|
||||
{
|
||||
input: "document",
|
||||
output: "HTMLDocument \u2192 " + TEST_URI,
|
||||
printOutput: "[object HTMLDocument]",
|
||||
inspectable: true,
|
||||
noClick: true,
|
||||
},
|
||||
|
||||
// 1
|
||||
{
|
||||
input: "window",
|
||||
output: "Window \u2192 " + TEST_URI,
|
||||
printOutput: "[object Window",
|
||||
inspectable: true,
|
||||
noClick: true,
|
||||
},
|
||||
|
||||
// 2
|
||||
{
|
||||
input: "document.body",
|
||||
output: "<body>",
|
||||
printOutput: "[object HTMLBodyElement]",
|
||||
inspectable: true,
|
||||
noClick: true,
|
||||
},
|
||||
|
||||
// 3
|
||||
{
|
||||
input: "document.body.dataset",
|
||||
output: "DOMStringMap {}",
|
||||
printOutput: "[object DOMStringMap]",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "DOMStringMap[0]",
|
||||
},
|
||||
|
||||
// 4
|
||||
{
|
||||
input: "document.body.classList",
|
||||
output: "DOMTokenList []",
|
||||
printOutput: '""',
|
||||
inspectable: true,
|
||||
variablesViewLabel: "DOMTokenList[0]",
|
||||
},
|
||||
|
||||
// 5
|
||||
{
|
||||
input: "window.location.href",
|
||||
output: '"' + TEST_URI + '"',
|
||||
},
|
||||
|
||||
// 6
|
||||
{
|
||||
input: "window.location",
|
||||
output: "Location \u2192 " + TEST_URI,
|
||||
printOutput: TEST_URI,
|
||||
inspectable: true,
|
||||
variablesViewLabel: "Location \u2192 test-console-output-03.html",
|
||||
},
|
||||
|
||||
// 7
|
||||
{
|
||||
input: "document.body.attributes",
|
||||
output: "MozNamedAttrMap []",
|
||||
printOutput: "[object MozNamedAttrMap]",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "MozNamedAttrMap[0]",
|
||||
},
|
||||
|
||||
// 8
|
||||
{
|
||||
input: "document.styleSheets",
|
||||
output: "StyleSheetList []",
|
||||
printOutput: "[object StyleSheetList",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "StyleSheetList[0]",
|
||||
},
|
||||
|
||||
// 9
|
||||
{
|
||||
input: "testBodyClassName()",
|
||||
output: '<body class="test1 tezt2">',
|
||||
printOutput: "[object HTMLBodyElement]",
|
||||
inspectable: true,
|
||||
noClick: true,
|
||||
},
|
||||
|
||||
// 10
|
||||
{
|
||||
input: "testBodyID()",
|
||||
output: '<body class="test1 tezt2" id="foobarid">',
|
||||
printOutput: "[object HTMLBodyElement]",
|
||||
inspectable: true,
|
||||
noClick: true,
|
||||
},
|
||||
|
||||
// 11
|
||||
{
|
||||
input: "document.body.classList",
|
||||
output: 'DOMTokenList ["test1", "tezt2"]',
|
||||
printOutput: '"test1 tezt2"',
|
||||
inspectable: true,
|
||||
variablesViewLabel: "DOMTokenList[2]",
|
||||
},
|
||||
|
||||
// 12
|
||||
{
|
||||
input: "testBodyDataset()",
|
||||
output: '<body class="test1 tezt2" id="foobarid"' +
|
||||
' data-preview="zuzu"<a>foo">',
|
||||
printOutput: "[object HTMLBodyElement]",
|
||||
inspectable: true,
|
||||
noClick: true,
|
||||
},
|
||||
|
||||
// 13
|
||||
{
|
||||
input: "document.body.dataset",
|
||||
output: 'DOMStringMap {preview: "zuzu\\"<a>foo"}',
|
||||
printOutput: "[object DOMStringMap]",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "DOMStringMap[1]",
|
||||
},
|
||||
|
||||
// 14
|
||||
{
|
||||
input: "document.body.attributes",
|
||||
output: 'MozNamedAttrMap [class="test1 tezt2", id="foobarid", ' +
|
||||
'data-preview="zuzu"<a>foo"]',
|
||||
printOutput: "[object MozNamedAttrMap]",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "MozNamedAttrMap[3]",
|
||||
},
|
||||
|
||||
// 15
|
||||
{
|
||||
input: "document.body.attributes[0]",
|
||||
output: 'class="test1 tezt2"',
|
||||
printOutput: "[object Attr]",
|
||||
inspectable: true,
|
||||
variablesViewLabel: 'class="test1 tezt2"',
|
||||
},
|
||||
];
|
||||
|
||||
function test() {
|
||||
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole().then((hud) => {
|
||||
return checkOutputForInputs(hud, inputTests);
|
||||
}).then(finishTest);
|
||||
}, true);
|
||||
}
|
120
browser/devtools/webconsole/test/browser_webconsole_output_04.js
Normal file
120
browser/devtools/webconsole/test/browser_webconsole_output_04.js
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Test the webconsole output for various types of objects.
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console-output-04.html";
|
||||
|
||||
let inputTests = [
|
||||
// 0
|
||||
{
|
||||
input: "testTextNode()",
|
||||
output: '#text "hello world!"',
|
||||
printOutput: "[object Text]",
|
||||
inspectable: true,
|
||||
noClick: true,
|
||||
},
|
||||
|
||||
// 1
|
||||
{
|
||||
input: "testCommentNode()",
|
||||
output: "<!--\n - Any copyright ",
|
||||
printOutput: "[object Comment]",
|
||||
inspectable: true,
|
||||
noClick: true,
|
||||
},
|
||||
|
||||
// 2
|
||||
{
|
||||
input: "testDocumentFragment()",
|
||||
output: 'DocumentFragment [<div id="foo1" class="bar">, <div id="foo3">]',
|
||||
printOutput: "[object DocumentFragment]",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "DocumentFragment[2]",
|
||||
},
|
||||
|
||||
// 3
|
||||
{
|
||||
input: "testError()",
|
||||
output: "TypeError: window.foobar is not a function\n" +
|
||||
"Stack trace:\n" +
|
||||
"testError@" + TEST_URI + ":44",
|
||||
printOutput: '"TypeError: window.foobar is not a function"',
|
||||
inspectable: true,
|
||||
variablesViewLabel: "TypeError",
|
||||
},
|
||||
|
||||
// 4
|
||||
{
|
||||
input: "testDOMException()",
|
||||
output: 'DOMException [SyntaxError: "An invalid or illegal string was specified"',
|
||||
printOutput: '[Exception... \\"An invalid or illegal string was specified\\"',
|
||||
inspectable: true,
|
||||
variablesViewLabel: "SyntaxError",
|
||||
},
|
||||
|
||||
// 5
|
||||
{
|
||||
input: "testCSSStyleDeclaration()",
|
||||
output: 'CSS2Properties {color: "green", font-size: "2em"}',
|
||||
printOutput: "[object CSS2Properties]",
|
||||
inspectable: true,
|
||||
noClick: true,
|
||||
},
|
||||
|
||||
// 6
|
||||
{
|
||||
input: "testStyleSheetList()",
|
||||
output: "StyleSheetList [CSSStyleSheet]",
|
||||
printOutput: "[object StyleSheetList",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "StyleSheetList[1]",
|
||||
},
|
||||
|
||||
// 7
|
||||
{
|
||||
input: "document.styleSheets[0]",
|
||||
output: "CSSStyleSheet",
|
||||
printOutput: "[object CSSStyleSheet]",
|
||||
inspectable: true,
|
||||
},
|
||||
|
||||
// 8
|
||||
{
|
||||
input: "document.styleSheets[0].cssRules",
|
||||
output: "CSSRuleList [CSSStyleRule, CSSMediaRule]",
|
||||
printOutput: "[object CSSRuleList",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "CSSRuleList[2]",
|
||||
},
|
||||
|
||||
// 9
|
||||
{
|
||||
input: "document.styleSheets[0].cssRules[0]",
|
||||
output: 'CSSStyleRule "p, div"',
|
||||
printOutput: "[object CSSStyleRule",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "CSSStyleRule",
|
||||
},
|
||||
|
||||
// 10
|
||||
{
|
||||
input: "document.styleSheets[0].cssRules[1]",
|
||||
output: 'CSSMediaRule "print"',
|
||||
printOutput: "[object CSSMediaRule",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "CSSMediaRule",
|
||||
},
|
||||
];
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole().then((hud) => {
|
||||
return checkOutputForInputs(hud, inputTests);
|
||||
}).then(finishTest);
|
||||
}, true);
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Test the webconsole output for DOM events.
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console-output-events.html";
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
Task.spawn(runner);
|
||||
}, true);
|
||||
|
||||
function* runner()
|
||||
{
|
||||
let hud = yield openConsole();
|
||||
|
||||
hud.jsterm.clearOutput();
|
||||
hud.jsterm.execute("testDOMEvents()");
|
||||
|
||||
yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
name: "testDOMEvents() output",
|
||||
text: "undefined",
|
||||
category: CATEGORY_OUTPUT,
|
||||
}],
|
||||
});
|
||||
|
||||
EventUtils.synthesizeMouse(content.document.body, 2, 2, {type: "mousemove"}, content);
|
||||
|
||||
yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
name: "console.log() output for mousemove",
|
||||
text: /"eventLogger" mousemove {target: .+, buttons: 1, clientX: \d+, clientY: \d+, layerX: \d+, layerY: \d+}/,
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
}],
|
||||
});
|
||||
|
||||
content.focus();
|
||||
EventUtils.synthesizeKey("a", {shiftKey: true}, content);
|
||||
|
||||
yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
name: "console.log() output for keypress",
|
||||
text: /"eventLogger" keypress Shift {target: .+, key: .+, charCode: \d+, keyCode: \d+}/,
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
}],
|
||||
});
|
||||
|
||||
finishTest();
|
||||
}
|
||||
}
|
@ -3,18 +3,18 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
let WebConsoleUtils, gDevTools, TargetFactory, console, promise, require;
|
||||
let WebConsoleUtils, TargetFactory, require;
|
||||
let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||
let {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
|
||||
(() => {
|
||||
gDevTools = Cu.import("resource:///modules/devtools/gDevTools.jsm", {}).gDevTools;
|
||||
console = Cu.import("resource://gre/modules/devtools/Console.jsm", {}).console;
|
||||
promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
|
||||
|
||||
let tools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
let utils = tools.require("devtools/toolkit/webconsole/utils");
|
||||
TargetFactory = tools.TargetFactory;
|
||||
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let utils = devtools.require("devtools/toolkit/webconsole/utils");
|
||||
TargetFactory = devtools.TargetFactory;
|
||||
WebConsoleUtils = utils.Utils;
|
||||
require = tools.require;
|
||||
require = devtools.require;
|
||||
})();
|
||||
// promise._reportErrors = true; // please never leave me.
|
||||
|
||||
@ -152,15 +152,20 @@ function findLogEntry(aString)
|
||||
* @param function [aCallback]
|
||||
* Optional function to invoke after the Web Console completes
|
||||
* initialization (web-console-created).
|
||||
* @return object
|
||||
* A promise that is resolved once the web console is open.
|
||||
*/
|
||||
function openConsole(aTab, aCallback = function() { })
|
||||
{
|
||||
let deferred = promise.defer();
|
||||
let target = TargetFactory.forTab(aTab || tab);
|
||||
gDevTools.showToolbox(target, "webconsole").then(function(toolbox) {
|
||||
let hud = toolbox.getCurrentPanel().hud;
|
||||
hud.jsterm._lazyVariablesView = false;
|
||||
aCallback(hud);
|
||||
deferred.resolve(hud);
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1259,3 +1264,153 @@ function whenDelayedStartupFinished(aWindow, aCallback)
|
||||
}
|
||||
}, "browser-delayed-startup-finished", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the web console output for the given inputs. Each input is checked for
|
||||
* the expected JS eval result, the result of calling print(), the result of
|
||||
* console.log(). The JS eval result is also checked if it opens the variables
|
||||
* view on click.
|
||||
*
|
||||
* @param object hud
|
||||
* The web console instance to work with.
|
||||
* @param array inputTests
|
||||
* An array of input tests. An input test element is an object. Each
|
||||
* object has the following properties:
|
||||
* - input: string, JS input value to execute.
|
||||
*
|
||||
* - output: string|RegExp, expected JS eval result.
|
||||
*
|
||||
* - inspectable: boolean, when true, the test runner expects the JS eval
|
||||
* result is an object that can be clicked for inspection.
|
||||
*
|
||||
* - noClick: boolean, when true, the test runner does not click the JS
|
||||
* eval result. Some objects, like |window|, have a lot of properties and
|
||||
* opening vview for them is very slow (they can cause timeouts in debug
|
||||
* builds).
|
||||
*
|
||||
* - printOutput: string|RegExp, optional, expected output for
|
||||
* |print(input)|. If this is not provided, printOutput = output.
|
||||
*
|
||||
* - variablesViewLabel: string|RegExp, optional, the expected variables
|
||||
* view label when the object is inspected. If this is not provided, then
|
||||
* |output| is used.
|
||||
*/
|
||||
function checkOutputForInputs(hud, inputTests)
|
||||
{
|
||||
let eventHandlers = new Set();
|
||||
|
||||
function* runner()
|
||||
{
|
||||
for (let [i, entry] of inputTests.entries()) {
|
||||
info("checkInput(" + i + "): " + entry.input);
|
||||
yield checkInput(entry);
|
||||
}
|
||||
|
||||
for (let fn of eventHandlers) {
|
||||
hud.jsterm.off("variablesview-open", fn);
|
||||
}
|
||||
}
|
||||
|
||||
function* checkInput(entry)
|
||||
{
|
||||
yield checkConsoleLog(entry);
|
||||
yield checkPrintOutput(entry);
|
||||
yield checkJSEval(entry);
|
||||
}
|
||||
|
||||
function checkConsoleLog(entry)
|
||||
{
|
||||
hud.jsterm.clearOutput();
|
||||
hud.jsterm.execute("console.log(" + entry.input + ")");
|
||||
|
||||
return waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
name: "console.log() output: " + entry.output,
|
||||
text: entry.output,
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
}],
|
||||
});
|
||||
}
|
||||
|
||||
function checkPrintOutput(entry)
|
||||
{
|
||||
hud.jsterm.clearOutput();
|
||||
hud.jsterm.execute("print(" + entry.input + ")");
|
||||
|
||||
let printOutput = entry.printOutput || entry.output;
|
||||
|
||||
return waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
name: "print() output: " + printOutput,
|
||||
text: printOutput,
|
||||
category: CATEGORY_OUTPUT,
|
||||
}],
|
||||
});
|
||||
}
|
||||
|
||||
function* checkJSEval(entry)
|
||||
{
|
||||
hud.jsterm.clearOutput();
|
||||
hud.jsterm.execute(entry.input);
|
||||
|
||||
let [result] = yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
name: "JS eval output: " + entry.output,
|
||||
text: entry.output,
|
||||
category: CATEGORY_OUTPUT,
|
||||
}],
|
||||
});
|
||||
|
||||
if (!entry.noClick) {
|
||||
let msg = [...result.matched][0];
|
||||
yield checkObjectClick(entry, msg);
|
||||
}
|
||||
}
|
||||
|
||||
function checkObjectClick(entry, msg)
|
||||
{
|
||||
let body = msg.querySelector(".body a") || msg.querySelector(".body");
|
||||
ok(body, "the message body");
|
||||
|
||||
let deferred = promise.defer();
|
||||
|
||||
entry._onVariablesViewOpen = onVariablesViewOpen.bind(null, entry, deferred);
|
||||
hud.jsterm.on("variablesview-open", entry._onVariablesViewOpen);
|
||||
eventHandlers.add(entry._onVariablesViewOpen);
|
||||
|
||||
body.scrollIntoView();
|
||||
EventUtils.synthesizeMouse(body, 2, 2, {}, hud.iframeWindow);
|
||||
|
||||
if (entry.inspectable) {
|
||||
info("message body tagName '" + body.tagName + "' className '" + body.className + "'");
|
||||
return deferred.promise; // wait for the panel to open if we need to.
|
||||
}
|
||||
|
||||
return promise.resolve(null);
|
||||
}
|
||||
|
||||
function onVariablesViewOpen(entry, deferred, event, view, options)
|
||||
{
|
||||
let label = entry.variablesViewLabel || entry.output;
|
||||
if (typeof label == "string" && options.label != label) {
|
||||
return;
|
||||
}
|
||||
if (label instanceof RegExp && !label.test(options.label)) {
|
||||
return;
|
||||
}
|
||||
|
||||
hud.jsterm.off("variablesview-open", entry._onVariablesViewOpen);
|
||||
eventHandlers.delete(entry._onVariablesViewOpen);
|
||||
entry._onVariablesViewOpen = null;
|
||||
|
||||
ok(entry.inspectable, "variables view was shown");
|
||||
|
||||
deferred.resolve(null);
|
||||
}
|
||||
|
||||
return Task.spawn(runner);
|
||||
}
|
||||
|
61
browser/devtools/webconsole/test/test-console-output-02.html
Normal file
61
browser/devtools/webconsole/test/test-console-output-02.html
Normal file
@ -0,0 +1,61 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html dir="ltr" lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test the web console output - 02</title>
|
||||
<!--
|
||||
- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
</head>
|
||||
<body>
|
||||
<p>hello world!</p>
|
||||
<script type="text/javascript">
|
||||
function testfn1() { return 42; }
|
||||
|
||||
var testobj1 = {
|
||||
testfn2: function() { return 42; },
|
||||
};
|
||||
|
||||
function testfn3() { return 42; }
|
||||
testfn3.displayName = "testfn3DisplayName";
|
||||
|
||||
var array1 = [1, 2, 3, "a", "b", "c", "4", "5"];
|
||||
|
||||
var array2 = ["a", document, document.body, document.body.dataset,
|
||||
document.body.classList];
|
||||
|
||||
var array3 = [1, window, null, "a", "b", undefined, false, "", -Infinity, testfn3, testobj1, "foo", "bar"];
|
||||
|
||||
var array4 = new Array(5);
|
||||
array4.push("test");
|
||||
array4.push(array4);
|
||||
|
||||
var typedarray1 = new Int32Array([1, 287, 8651, 40983, 8754]);
|
||||
|
||||
var set1 = new Set([1, 2, null, array3, "a", "b", undefined, document.head]);
|
||||
set1.add(set1);
|
||||
|
||||
var testobj2 = {a: "b", c: "d", e: 1, f: "2"};
|
||||
testobj2.foo = testobj1;
|
||||
testobj2.bar = testobj2;
|
||||
Object.defineProperty(testobj2, "getterTest", {
|
||||
enumerable: true,
|
||||
get: function() {
|
||||
return 42;
|
||||
},
|
||||
});
|
||||
|
||||
var testobj3 = {a: "b", c: "d", e: 1, f: "2", g: true, h: null, i: undefined,
|
||||
j: "", k: document.styleSheets, l: document.body.childNodes,
|
||||
o: new Array(125), m: document.head};
|
||||
|
||||
var testobj4 = {a: "b", c: "d"};
|
||||
Object.defineProperty(testobj4, "nonEnumerable", { value: "hello world" });
|
||||
|
||||
var map1 = new Map([["a", "b"], [document.body.children, testobj2]]);
|
||||
map1.set(map1, set1);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
30
browser/devtools/webconsole/test/test-console-output-03.html
Normal file
30
browser/devtools/webconsole/test/test-console-output-03.html
Normal file
@ -0,0 +1,30 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html dir="ltr" lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test the web console output - 03</title>
|
||||
<!--
|
||||
- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
</head>
|
||||
<body>
|
||||
<p>hello world!</p>
|
||||
<script type="text/javascript">
|
||||
function testBodyClassName() {
|
||||
document.body.className = "test1 tezt2";
|
||||
return document.body;
|
||||
}
|
||||
|
||||
function testBodyID() {
|
||||
document.body.id = 'foobarid';
|
||||
return document.body;
|
||||
}
|
||||
|
||||
function testBodyDataset() {
|
||||
document.body.dataset.preview = 'zuzu"<a>foo';
|
||||
return document.body;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
77
browser/devtools/webconsole/test/test-console-output-04.html
Normal file
77
browser/devtools/webconsole/test/test-console-output-04.html
Normal file
@ -0,0 +1,77 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html dir="ltr" lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test the web console output - 04</title>
|
||||
<!--
|
||||
- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
</head>
|
||||
<body>
|
||||
<p>hello world!</p>
|
||||
<script type="text/javascript">
|
||||
function testTextNode() {
|
||||
return document.querySelector("p").childNodes[0];
|
||||
}
|
||||
|
||||
function testCommentNode() {
|
||||
return document.head.childNodes[5];
|
||||
}
|
||||
|
||||
function testDocumentFragment() {
|
||||
var frag = document.createDocumentFragment();
|
||||
|
||||
var div = document.createElement("div");
|
||||
div.id = "foo1";
|
||||
div.className = "bar";
|
||||
frag.appendChild(div);
|
||||
|
||||
var span = document.createElement("span");
|
||||
span.id = "foo2";
|
||||
span.textContent = "hello world";
|
||||
div.appendChild(span);
|
||||
|
||||
var div2 = document.createElement("div");
|
||||
div2.id = "foo3";
|
||||
frag.appendChild(div2);
|
||||
|
||||
return frag;
|
||||
}
|
||||
|
||||
function testError() {
|
||||
try {
|
||||
window.foobar("a");
|
||||
} catch (ex) {
|
||||
return ex;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function testDOMException() {
|
||||
try {
|
||||
var foo = document.querySelector("foo;()bar!");
|
||||
} catch (ex) {
|
||||
return ex;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function testCSSStyleDeclaration() {
|
||||
document.body.style = 'color: green; font-size: 2em';
|
||||
return document.body.style;
|
||||
}
|
||||
|
||||
function testStyleSheetList() {
|
||||
var style = document.querySelector("style");
|
||||
if (!style) {
|
||||
style = document.createElement("style");
|
||||
style.textContent = "p, div { color: blue; font-weight: bold }\n" +
|
||||
"@media print { p { background-color: yellow } }";
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
return document.styleSheets;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html dir="ltr" lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test the web console output for DOM events</title>
|
||||
<!--
|
||||
- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
</head>
|
||||
<body>
|
||||
<p>hello world!</p>
|
||||
<script type="text/javascript">
|
||||
function testDOMEvents() {
|
||||
function eventLogger(ev) {
|
||||
console.log("eventLogger", ev);
|
||||
}
|
||||
document.addEventListener("mousemove", eventLogger);
|
||||
document.addEventListener("keypress", eventLogger);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1183,10 +1183,6 @@ WebConsoleFrame.prototype = {
|
||||
let clipboardArray = [];
|
||||
args.forEach((aValue) => {
|
||||
clipboardArray.push(VariablesView.getString(aValue));
|
||||
if (aValue && typeof aValue == "object" &&
|
||||
aValue.type == "longString") {
|
||||
clipboardArray.push(l10n.getStr("longStringEllipsis"));
|
||||
}
|
||||
});
|
||||
clipboardText = clipboardArray.join(" ");
|
||||
break;
|
||||
@ -3103,7 +3099,7 @@ JSTerm.prototype = {
|
||||
aAfterMessage._objectActors.add(helperResult.object.actor);
|
||||
}
|
||||
this.openVariablesView({
|
||||
label: VariablesView.getString(helperResult.object),
|
||||
label: VariablesView.getString(helperResult.object, { concise: true }),
|
||||
objectActor: helperResult.object,
|
||||
});
|
||||
break;
|
||||
@ -4265,6 +4261,7 @@ JSTerm.prototype = {
|
||||
popup.selectNextItem();
|
||||
}
|
||||
|
||||
this.emit("autocomplete-updated");
|
||||
aCallback && aCallback(this);
|
||||
},
|
||||
|
||||
|
5
browser/locales/en-US/chrome/browser/aboutAccounts.dtd
Normal file
5
browser/locales/en-US/chrome/browser/aboutAccounts.dtd
Normal file
@ -0,0 +1,5 @@
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!ENTITY aboutAccounts.pageTitle "&brandShortName; Accounts">
|
@ -202,8 +202,8 @@ loadingText=Loading\u2026
|
||||
# viewer when there is an error loading a file
|
||||
errorLoadingText=Error loading source:\n
|
||||
|
||||
# LOCALIZATION NOTE (emptyStackText): The text that is displayed in the watch
|
||||
# expressions list to add a new item.
|
||||
# LOCALIZATION NOTE (addWatchExpressionText): The text that is displayed in the
|
||||
# watch expressions list to add a new item.
|
||||
addWatchExpressionText=Add watch expression
|
||||
|
||||
# LOCALIZATION NOTE (emptyVariablesText): The text that is displayed in the
|
||||
@ -225,6 +225,19 @@ watchExpressionsScopeLabel=Watch expressions
|
||||
# the global scope.
|
||||
globalScopeLabel=Global
|
||||
|
||||
# LOCALIZATION NOTE (variablesViewErrorStacktrace): This is the text that is
|
||||
# shown before the stack trace in an error.
|
||||
variablesViewErrorStacktrace=Stack trace:
|
||||
|
||||
# LOCALIZATION NOTE (variablesViewMoreObjects): the text that is displayed
|
||||
# when you have an object preview that does not show all of the elements. At the end of the list
|
||||
# you see "N more..." in the web console output.
|
||||
# This is a semi-colon list of plural forms.
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
# #1 number of remaining items in the object
|
||||
# example: 3 more…
|
||||
variablesViewMoreObjects=#1 more…;#1 more…
|
||||
|
||||
# LOCALIZATION NOTE (variablesEditableNameTooltip): The text that is displayed
|
||||
# in the variables list on an item with an editable name.
|
||||
variablesEditableNameTooltip=Double click to edit
|
||||
|
@ -33,6 +33,8 @@
|
||||
<!ENTITY setup.choosePassword.accesskey "P">
|
||||
<!ENTITY setup.confirmPassword.label "Confirm Password">
|
||||
<!ENTITY setup.confirmPassword.accesskey "m">
|
||||
<!ENTITY setup.setupMetro.label "Sync with Windows 8 style &brandShortName;">
|
||||
<!ENTITY setup.setupMetro.accesskey "S">
|
||||
|
||||
<!-- LOCALIZATION NOTE: tosAgree1, tosLink, tosAgree2, ppLink, tosAgree3 are
|
||||
joined with implicit white space, so spaces in the strings aren't necessary -->
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
@AB_CD@.jar:
|
||||
% locale browser @AB_CD@ %locale/browser/
|
||||
locale/browser/aboutAccounts.dtd (%chrome/browser/aboutAccounts.dtd)
|
||||
locale/browser/aboutCertError.dtd (%chrome/browser/aboutCertError.dtd)
|
||||
locale/browser/aboutDialog.dtd (%chrome/browser/aboutDialog.dtd)
|
||||
locale/browser/aboutPrivateBrowsing.dtd (%chrome/browser/aboutPrivateBrowsing.dtd)
|
||||
|
@ -100,11 +100,26 @@ XPCOMUtils.defineLazyGetter(this, "DEFAULT_ITEMS", function() {
|
||||
return result;
|
||||
});
|
||||
|
||||
const ALL_BUILTIN_ITEMS = [
|
||||
"fullscreen-button",
|
||||
"switch-to-metro-button",
|
||||
"bookmarks-menu-button",
|
||||
];
|
||||
XPCOMUtils.defineLazyGetter(this, "ALL_BUILTIN_ITEMS", function() {
|
||||
// These special cases are for click events on built-in items that are
|
||||
// contained within customizable items (like the navigation widget).
|
||||
const SPECIAL_CASES = [
|
||||
"back-button",
|
||||
"forward-button",
|
||||
"urlbar-stop-button",
|
||||
"urlbar-go-button",
|
||||
"urlbar-reload-button",
|
||||
"searchbar",
|
||||
"cut-button",
|
||||
"copy-button",
|
||||
"paste-button",
|
||||
"zoom-out-button",
|
||||
"zoom-reset-button",
|
||||
"zoom-in-button",
|
||||
]
|
||||
return DEFAULT_ITEMS.concat(PALETTE_ITEMS)
|
||||
.concat(SPECIAL_CASES);
|
||||
});
|
||||
|
||||
const OTHER_MOUSEUP_MONITORED_ITEMS = [
|
||||
"PlacesChevron",
|
||||
@ -318,6 +333,14 @@ this.BrowserUITelemetry = {
|
||||
// Base case - we clicked directly on one of our built-in items,
|
||||
// and we can go ahead and register that click.
|
||||
this._countMouseUpEvent("click-builtin-item", item.id, aEvent.button);
|
||||
return;
|
||||
}
|
||||
|
||||
// If not, we need to check if one of the ancestors of the clicked
|
||||
// item is in our list of built-in items to check.
|
||||
let candidate = getIDBasedOnFirstIDedAncestor(item);
|
||||
if (ALL_BUILTIN_ITEMS.indexOf(candidate) != -1) {
|
||||
this._countMouseUpEvent("click-builtin-item", candidate, aEvent.button);
|
||||
}
|
||||
},
|
||||
|
||||
@ -396,4 +419,4 @@ function getIDBasedOnFirstIDedAncestor(aNode) {
|
||||
}
|
||||
|
||||
return aNode.id;
|
||||
}
|
||||
}
|
@ -51,7 +51,7 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.devtools-toolbarbutton:not([checked=true]):hover:active {
|
||||
.devtools-toolbarbutton:not([checked]):hover:active {
|
||||
border-color: hsla(210,8%,5%,.6);
|
||||
background: linear-gradient(hsla(220,6%,10%,.3), hsla(212,7%,57%,.15) 65%, hsla(212,7%,57%,.3));
|
||||
box-shadow: 0 0 3px hsla(210,8%,5%,.25) inset, 0 1px 3px hsla(210,8%,5%,.25) inset, 0 1px 0 hsla(210,16%,76%,.15);
|
||||
@ -282,28 +282,28 @@
|
||||
background-image: linear-gradient(hsla(206,37%,4%,.4), hsla(206,37%,4%,.4)), @smallSeparator@;
|
||||
}
|
||||
|
||||
.devtools-sidebar-tabs > tabs > tab[selected=true] + tab {
|
||||
.devtools-sidebar-tabs > tabs > tab[selected] + tab {
|
||||
background-image: linear-gradient(transparent, transparent), @solidSeparator@;
|
||||
}
|
||||
|
||||
.devtools-sidebar-tabs > tabs > tab[selected=true] + tab:hover {
|
||||
.devtools-sidebar-tabs > tabs > tab[selected] + tab:hover {
|
||||
background-image: linear-gradient(hsla(206,37%,4%,.2), hsla(206,37%,4%,.2)), @solidSeparator@;
|
||||
}
|
||||
|
||||
.devtools-sidebar-tabs > tabs > tab[selected=true] + tab:hover:active {
|
||||
.devtools-sidebar-tabs > tabs > tab[selected] + tab:hover:active {
|
||||
background-image: linear-gradient(hsla(206,37%,4%,.4), hsla(206,37%,4%,.4)), @solidSeparator@;
|
||||
}
|
||||
|
||||
.devtools-sidebar-tabs > tabs > tab[selected=true] {
|
||||
.devtools-sidebar-tabs > tabs > tab[selected] {
|
||||
color: #f5f7fa;
|
||||
background-image: linear-gradient(#1d4f73, #1d4f73), @solidSeparator@;
|
||||
}
|
||||
|
||||
.devtools-sidebar-tabs > tabs > tab[selected=true]:hover {
|
||||
.devtools-sidebar-tabs > tabs > tab[selected]:hover {
|
||||
background-image: linear-gradient(#274f64, #274f64), @solidSeparator@;
|
||||
}
|
||||
|
||||
.devtools-sidebar-tabs > tabs > tab[selected=true]:hover:active {
|
||||
.devtools-sidebar-tabs > tabs > tab[selected]:hover:active {
|
||||
background-image: linear-gradient(#1f3e4f, #1f3e4f), @solidSeparator@;
|
||||
}
|
||||
|
||||
@ -520,7 +520,7 @@
|
||||
}
|
||||
|
||||
.devtools-tab:active > image,
|
||||
.devtools-tab[selected=true] > image {
|
||||
.devtools-tab[selected] > image {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@ -534,7 +534,7 @@
|
||||
color: #f5f7fa;
|
||||
}
|
||||
|
||||
#toolbox-tabs .devtools-tab[selected=true] {
|
||||
#toolbox-tabs .devtools-tab[selected] {
|
||||
color: #f5f7fa;
|
||||
background-color: #1a4666;
|
||||
box-shadow: 0 2px 0 #d7f1ff inset,
|
||||
@ -542,32 +542,32 @@
|
||||
0 -2px 0 rgba(0,0,0,.2) inset;
|
||||
}
|
||||
|
||||
.devtools-tab[selected=true]:not(:first-child),
|
||||
.devtools-tab.highlighted:not(:first-child) {
|
||||
.devtools-tab[selected]:not(:first-child),
|
||||
.devtools-tab[highlighted]:not(:first-child) {
|
||||
border-width: 0;
|
||||
-moz-padding-start: 1px;
|
||||
}
|
||||
|
||||
.devtools-tab[selected=true]:last-child,
|
||||
.devtools-tab.highlighted:last-child {
|
||||
.devtools-tab[selected]:last-child,
|
||||
.devtools-tab[highlighted]:last-child {
|
||||
-moz-padding-end: 1px;
|
||||
}
|
||||
|
||||
.devtools-tab[selected=true] + .devtools-tab,
|
||||
.devtools-tab.highlighted + .devtools-tab {
|
||||
.devtools-tab[selected] + .devtools-tab,
|
||||
.devtools-tab[highlighted] + .devtools-tab {
|
||||
-moz-border-start-width: 0;
|
||||
-moz-padding-start: 1px;
|
||||
}
|
||||
|
||||
.devtools-tab:not([selected=true]).highlighted {
|
||||
.devtools-tab:not([selected])[highlighted] {
|
||||
color: #f5f7fa;
|
||||
background-color: hsla(99,100%,14%,.2);
|
||||
box-shadow: 0 2px 0 #7bc107 inset;
|
||||
}
|
||||
|
||||
.devtools-tab:not(.highlighted) > .highlighted-icon,
|
||||
.devtools-tab[selected=true] > .highlighted-icon,
|
||||
.devtools-tab:not([selected=true]).highlighted > .default-icon {
|
||||
.devtools-tab:not([highlighted]) > .highlighted-icon,
|
||||
.devtools-tab[selected] > .highlighted-icon,
|
||||
.devtools-tab:not([selected])[highlighted] > .default-icon {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
|
@ -686,7 +686,6 @@ GK_ATOM(ondisabled, "ondisabled")
|
||||
GK_ATOM(ondischargingtimechange, "ondischargingtimechange")
|
||||
GK_ATOM(ondisconnected, "ondisconnected")
|
||||
GK_ATOM(ondisconnecting, "ondisconnecting")
|
||||
GK_ATOM(ondiscoverystatechanged, "ondiscoverystatechanged")
|
||||
GK_ATOM(ondownloading, "ondownloading")
|
||||
GK_ATOM(onDOMActivate, "onDOMActivate")
|
||||
GK_ATOM(onDOMAttrModified, "onDOMAttrModified")
|
||||
|
@ -48,10 +48,6 @@ const kEventConstructors = {
|
||||
return new BluetoothDeviceEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
BluetoothDiscoveryStateChangedEvent: { create: function (aName, aProps) {
|
||||
return new BluetoothDiscoveryStateChangedEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
BluetoothStatusChangedEvent: { create: function (aName, aProps) {
|
||||
return new BluetoothStatusChangedEvent(aName, aProps);
|
||||
},
|
||||
|
@ -23,7 +23,7 @@ interface nsIMarkupDocumentViewer;
|
||||
|
||||
[ref] native nsIMarkupDocumentViewerTArray(nsTArray<nsCOMPtr<nsIMarkupDocumentViewer> >);
|
||||
|
||||
[scriptable, uuid(3528324f-f5d3-4724-bd8d-9233a7114112)]
|
||||
[scriptable, uuid(7aea9561-5346-401c-b40e-418688da2d0d)]
|
||||
interface nsIMarkupDocumentViewer : nsISupports
|
||||
{
|
||||
|
||||
@ -82,6 +82,18 @@ interface nsIMarkupDocumentViewer : nsISupports
|
||||
*/
|
||||
void changeMaxLineBoxWidth(in int32_t maxLineBoxWidth);
|
||||
|
||||
/**
|
||||
* Instruct the refresh driver to discontinue painting until further
|
||||
* notice.
|
||||
*/
|
||||
void pausePainting();
|
||||
|
||||
/**
|
||||
* Instruct the refresh driver to resume painting after a previous call to
|
||||
* pausePainting().
|
||||
*/
|
||||
void resumePainting();
|
||||
|
||||
/*
|
||||
* Render the document as if being viewed on a device with the specified
|
||||
* media type. This will cause a reflow.
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "nsCxPusher.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsIDOMBluetoothDeviceEvent.h"
|
||||
#include "nsIDOMBluetoothDiscoveryStateChangedEvent.h"
|
||||
#include "nsIDOMBluetoothStatusChangedEvent.h"
|
||||
#include "nsTArrayHelpers.h"
|
||||
#include "DOMRequest.h"
|
||||
@ -322,19 +321,6 @@ BluetoothAdapter::Notify(const BluetoothSignal& aData)
|
||||
for (uint32_t i = 0, propCount = arr.Length(); i < propCount; ++i) {
|
||||
SetPropertyByValue(arr[i]);
|
||||
}
|
||||
} else if (aData.name().EqualsLiteral(DISCOVERY_STATE_CHANGED_ID)) {
|
||||
MOZ_ASSERT(v.type() == BluetoothValue::Tbool);
|
||||
bool isDiscovering = v.get_bool();
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
NS_NewDOMBluetoothDiscoveryStateChangedEvent(
|
||||
getter_AddRefs(event), this, nullptr, nullptr);
|
||||
|
||||
nsCOMPtr<nsIDOMBluetoothDiscoveryStateChangedEvent> e =
|
||||
do_QueryInterface(event);
|
||||
e->InitBluetoothDiscoveryStateChangedEvent(aData.name(), false, false,
|
||||
isDiscovering);
|
||||
DispatchTrustedEvent(event);
|
||||
} else if (aData.name().EqualsLiteral(PAIRED_STATUS_CHANGED_ID) ||
|
||||
aData.name().EqualsLiteral(HFP_STATUS_CHANGED_ID) ||
|
||||
aData.name().EqualsLiteral(SCO_STATUS_CHANGED_ID) ||
|
||||
|
@ -147,7 +147,6 @@ public:
|
||||
SendMediaPlayStatus(const MediaPlayStatus& aMediaPlayStatus, ErrorResult& aRv);
|
||||
|
||||
IMPL_EVENT_HANDLER(devicefound);
|
||||
IMPL_EVENT_HANDLER(discoverystatechanged);
|
||||
IMPL_EVENT_HANDLER(a2dpstatuschanged);
|
||||
IMPL_EVENT_HANDLER(hfpstatuschanged);
|
||||
IMPL_EVENT_HANDLER(pairedstatuschanged);
|
||||
|
@ -92,11 +92,6 @@ extern bool gBluetoothDebugFlag;
|
||||
*/
|
||||
#define PAIRED_STATUS_CHANGED_ID "pairedstatuschanged"
|
||||
|
||||
/**
|
||||
* This event would be fired when discovery procedure starts or stops.
|
||||
*/
|
||||
#define DISCOVERY_STATE_CHANGED_ID "discoverystatechanged"
|
||||
|
||||
/**
|
||||
* When receiving a query about current play status from remote device, we'll
|
||||
* dispatch an event.
|
||||
|
@ -50,6 +50,7 @@ static InfallibleTArray<nsString> sAdapterBondedAddressArray;
|
||||
static InfallibleTArray<BluetoothNamedValue> sRemoteDevicesPack;
|
||||
static nsTArray<nsRefPtr<BluetoothProfileController> > sControllerArray;
|
||||
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sBondingRunnableArray;
|
||||
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sChangeDiscoveryRunnableArray;
|
||||
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sGetDeviceRunnableArray;
|
||||
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sSetPropertyRunnableArray;
|
||||
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sUnbondingRunnableArray;
|
||||
@ -510,16 +511,12 @@ DiscoveryStateChangedCallback(bt_discovery_state_t aState)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
bool isDiscovering = (aState == BT_DISCOVERY_STARTED);
|
||||
if (!sChangeDiscoveryRunnableArray.IsEmpty()) {
|
||||
BluetoothValue values(true);
|
||||
DispatchBluetoothReply(sChangeDiscoveryRunnableArray[0],
|
||||
values, EmptyString());
|
||||
|
||||
BluetoothSignal signal(NS_LITERAL_STRING(DISCOVERY_STATE_CHANGED_ID),
|
||||
NS_LITERAL_STRING(KEY_ADAPTER),
|
||||
isDiscovering);
|
||||
|
||||
nsRefPtr<DistributeBluetoothSignalTask>
|
||||
t = new DistributeBluetoothSignalTask(signal);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(t))) {
|
||||
BT_WARNING("Failed to dispatch to main thread!");
|
||||
sChangeDiscoveryRunnableArray.RemoveElementAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -936,17 +933,17 @@ BluetoothServiceBluedroid::StartDiscoveryInternal(
|
||||
if (!IsReady()) {
|
||||
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
|
||||
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int ret = sBtInterface->start_discovery();
|
||||
if (ret != BT_STATUS_SUCCESS) {
|
||||
ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("StartDiscovery"));
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DispatchBluetoothReply(aRunnable, true, EmptyString());
|
||||
|
||||
sChangeDiscoveryRunnableArray.AppendElement(aRunnable);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -965,10 +962,10 @@ BluetoothServiceBluedroid::StopDiscoveryInternal(
|
||||
int ret = sBtInterface->cancel_discovery();
|
||||
if (ret != BT_STATUS_SUCCESS) {
|
||||
ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("StopDiscovery"));
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DispatchBluetoothReply(aRunnable, true, EmptyString());
|
||||
sChangeDiscoveryRunnableArray.AppendElement(aRunnable);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1560,20 +1560,6 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
|
||||
errorStr,
|
||||
sAdapterProperties,
|
||||
ArrayLength(sAdapterProperties));
|
||||
|
||||
BluetoothNamedValue& property = v.get_ArrayOfBluetoothNamedValue()[0];
|
||||
if (property.name().EqualsLiteral("Discovering")) {
|
||||
bool isDiscovering = property.value();
|
||||
BluetoothSignal signal(NS_LITERAL_STRING(DISCOVERY_STATE_CHANGED_ID),
|
||||
NS_LITERAL_STRING(KEY_ADAPTER),
|
||||
isDiscovering);
|
||||
|
||||
nsRefPtr<DistributeBluetoothSignalTask>
|
||||
t = new DistributeBluetoothSignalTask(signal);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(t))) {
|
||||
BT_WARNING("Failed to dispatch to main thread!");
|
||||
}
|
||||
}
|
||||
} else if (dbus_message_is_signal(aMsg, DBUS_DEVICE_IFACE,
|
||||
"PropertyChanged")) {
|
||||
ParsePropertyChange(aMsg,
|
||||
|
@ -8,7 +8,6 @@ if CONFIG['MOZ_B2G_BT']:
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDOMBluetoothDevice.idl',
|
||||
'nsIDOMBluetoothDeviceEvent.idl',
|
||||
'nsIDOMBluetoothDiscoveryStateChangedEvent.idl',
|
||||
'nsIDOMBluetoothStatusChangedEvent.idl',
|
||||
]
|
||||
XPIDL_MODULE = 'dom_bluetooth'
|
||||
|
@ -1,22 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
[scriptable, builtinclass, uuid(9de639cb-71c4-4144-8462-09763ec87c20)]
|
||||
interface nsIDOMBluetoothDiscoveryStateChangedEvent : nsIDOMEvent
|
||||
{
|
||||
readonly attribute boolean discovering;
|
||||
|
||||
[noscript]
|
||||
void initBluetoothDiscoveryStateChangedEvent(in DOMString aType,
|
||||
in boolean aCanBubble,
|
||||
in boolean aCancelable,
|
||||
in boolean aDiscovering);
|
||||
};
|
||||
|
||||
dictionary BluetoothDiscoveryStateChangedEventInit : EventInit
|
||||
{
|
||||
bool discovering;
|
||||
};
|
@ -60,7 +60,7 @@ let CERTIFICATE_ERROR_PAGE_PREF = 'security.alternate_certificate_error_page';
|
||||
let NS_ERROR_MODULE_BASE_OFFSET = 0x45;
|
||||
let NS_ERROR_MODULE_SECURITY= 21;
|
||||
function NS_ERROR_GET_MODULE(err) {
|
||||
return ((((err) >> 16) - NS_ERROR_MODULE_BASE_OFFSET) & 0x1fff)
|
||||
return ((((err) >> 16) - NS_ERROR_MODULE_BASE_OFFSET) & 0x1fff);
|
||||
}
|
||||
|
||||
function NS_ERROR_GET_CODE(err) {
|
||||
@ -82,7 +82,7 @@ let SSL_ERROR_BAD_CERT_DOMAIN = (SSL_ERROR_BASE + 12);
|
||||
|
||||
function getErrorClass(errorCode) {
|
||||
let NSPRCode = -1 * NS_ERROR_GET_CODE(errorCode);
|
||||
|
||||
|
||||
switch (NSPRCode) {
|
||||
case SEC_ERROR_UNKNOWN_ISSUER:
|
||||
case SEC_ERROR_CA_CERT_INVALID:
|
||||
@ -129,6 +129,9 @@ function BrowserElementChild() {
|
||||
|
||||
this._nextPaintHandler = null;
|
||||
|
||||
this._isContentWindowCreated = false;
|
||||
this._pendingSetInputMethodActive = [];
|
||||
|
||||
this._init();
|
||||
};
|
||||
|
||||
@ -566,6 +569,11 @@ BrowserElementChild.prototype = {
|
||||
this._addMozAfterPaintHandler(function () {
|
||||
sendAsyncMsg('documentfirstpaint');
|
||||
});
|
||||
this._isContentWindowCreated = true;
|
||||
// Handle pending SetInputMethodActive request.
|
||||
while (this._pendingSetInputMethodActive.length > 0) {
|
||||
this._recvSetInputMethodActive(this._pendingSetInputMethodActive.shift());
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -904,6 +912,17 @@ BrowserElementChild.prototype = {
|
||||
|
||||
_recvSetInputMethodActive: function(data) {
|
||||
let msgData = { id: data.json.id };
|
||||
if (!this._isContentWindowCreated) {
|
||||
if (data.json.args.isActive) {
|
||||
// To activate the input method, we should wait before the content
|
||||
// window is ready.
|
||||
this._pendingSetInputMethodActive.push(data);
|
||||
return;
|
||||
}
|
||||
sendAsyncMsg('got-set-input-method-active', msgData);
|
||||
msgData.successRv = null;
|
||||
return;
|
||||
}
|
||||
// Unwrap to access webpage content.
|
||||
let nav = XPCNativeWrapper.unwrap(content.document.defaultView.navigator);
|
||||
if (nav.mozInputMethod) {
|
||||
@ -977,7 +996,7 @@ BrowserElementChild.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_ERROR_GET_MODULE(status) == NS_ERROR_MODULE_SECURITY &&
|
||||
if (NS_ERROR_GET_MODULE(status) == NS_ERROR_MODULE_SECURITY &&
|
||||
getErrorClass(status) == Ci.nsINSSErrorsService.ERROR_CLASS_BAD_CERT) {
|
||||
|
||||
// XXX Is there a point firing the event if the error page is not
|
||||
|
@ -198,7 +198,6 @@ function createDOMDownloadObject(aWindow, aDownload) {
|
||||
|
||||
function DOMDownloadImpl() {
|
||||
debug("DOMDownloadImpl constructor ");
|
||||
|
||||
this.wrappedJSObject = this;
|
||||
this.totalBytes = 0;
|
||||
this.currentBytes = 0;
|
||||
@ -206,10 +205,8 @@ function DOMDownloadImpl() {
|
||||
this.path = null;
|
||||
this.state = "stopped";
|
||||
this.contentType = null;
|
||||
|
||||
/* fields that require getters/setters */
|
||||
this._error = null;
|
||||
this._startTime = new Date();
|
||||
this.startTime = Date.now();
|
||||
this.error = null;
|
||||
|
||||
/* private fields */
|
||||
this.id = null;
|
||||
@ -247,27 +244,6 @@ DOMDownloadImpl.prototype = {
|
||||
return this.__DOM_IMPL__.getEventHandler("onstatechange");
|
||||
},
|
||||
|
||||
get error() {
|
||||
return this._error;
|
||||
},
|
||||
|
||||
set error(aError) {
|
||||
this._error = aError;
|
||||
},
|
||||
|
||||
get startTime() {
|
||||
return this._startTime;
|
||||
},
|
||||
|
||||
set startTime(aStartTime) {
|
||||
if (aStartTime instanceof Date) {
|
||||
this._startTime = aStartTime;
|
||||
}
|
||||
else {
|
||||
this._startTime = new Date(aStartTime);
|
||||
}
|
||||
},
|
||||
|
||||
_init: function(aWindow, aDownload) {
|
||||
this._window = aWindow;
|
||||
this.id = aDownload.id;
|
||||
|
@ -24,10 +24,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=938023
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var index = -1;
|
||||
var todayDate = new Date();
|
||||
var baseServeURL = "http://mochi.test:8888/tests/dom/downloads/tests/";
|
||||
var baseDownloadPath = "/mnt/sdcard/downloads/";
|
||||
var lastKnownCurrentBytes = 0;
|
||||
|
||||
function next() {
|
||||
index += 1;
|
||||
@ -42,54 +38,16 @@ function next() {
|
||||
}
|
||||
}
|
||||
|
||||
function checkConsistentDownloadAttributes(download) {
|
||||
var href = document.getElementById("download1").getAttribute("href");
|
||||
var expectedServeURL = baseServeURL + href;
|
||||
var expectedDownloadPath = baseDownloadPath + "test.bin";
|
||||
|
||||
// bug 945323: Download path isn't honoring download attribute
|
||||
todo(download.path === expectedDownloadPath,
|
||||
"Download path = " + expectedDownloadPath);
|
||||
|
||||
ok(download.startTime >= todayDate,
|
||||
"Download start time should be greater than or equal to today");
|
||||
|
||||
is(download.error, null, "Download does not have an error");
|
||||
|
||||
is(download.url, expectedServeURL,
|
||||
"Download URL = " + expectedServeURL);
|
||||
ok(download.id !== null, "Download id is defined");
|
||||
is(download.contentType, "application/octet-stream",
|
||||
"Download content type is application/octet-stream");
|
||||
}
|
||||
|
||||
function downloadChange(evt) {
|
||||
var download = evt.download;
|
||||
checkConsistentDownloadAttributes(download);
|
||||
is(download.totalBytes, 1024, "Download total size is 1024 bytes");
|
||||
|
||||
if (download.state === "succeeded") {
|
||||
is(download.currentBytes, 1024, "Download current size is 1024 bytes");
|
||||
if (download.state == "succeeded") {
|
||||
ok(download.totalBytes == 1024, "Download size is 1024 bytes.");
|
||||
ok(download.contentType == "application/octet-stream",
|
||||
"contentType is application/octet-stream.");
|
||||
SimpleTest.finish();
|
||||
} else if (download.state === "downloading") {
|
||||
ok(download.currentBytes > lastKnownCurrentBytes,
|
||||
"Download current size is larger than last download change event");
|
||||
lastKnownCurrentBytes = download.currentBytes;
|
||||
} else {
|
||||
ok(false, "Unexpected download state = " + download.state);
|
||||
}
|
||||
}
|
||||
|
||||
function downloadStart(evt) {
|
||||
var download = evt.download;
|
||||
checkConsistentDownloadAttributes(download);
|
||||
|
||||
is(download.currentBytes, 0, "Download current size is zero");
|
||||
is(download.state, "downloading", "Download state is downloading");
|
||||
|
||||
download.onstatechange = downloadChange;
|
||||
}
|
||||
|
||||
var steps = [
|
||||
// Start by setting the pref to true.
|
||||
function() {
|
||||
@ -103,7 +61,11 @@ var steps = [
|
||||
SpecialPowers.pushPermissions([
|
||||
{type: "downloads", allow: true, context: document}
|
||||
], function() {
|
||||
navigator.mozDownloadManager.ondownloadstart = downloadStart;
|
||||
navigator.mozDownloadManager.ondownloadstart =
|
||||
function(evt) {
|
||||
ok(true, "Download started");
|
||||
evt.download.addEventListener("statechange", downloadChange);
|
||||
}
|
||||
next();
|
||||
});
|
||||
},
|
||||
@ -120,4 +82,3 @@ next();
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
18
dom/inputmethod/mochitest/file_inputmethod.html
Normal file
18
dom/inputmethod/mochitest/file_inputmethod.html
Normal file
@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
var im = navigator.mozInputMethod;
|
||||
if (im) {
|
||||
// Automatically append location hash to current input field.
|
||||
im.oninputcontextchange = function() {
|
||||
var ctx = im.inputcontext;
|
||||
if (ctx) {
|
||||
intervalId = setTimeout(function() {
|
||||
ctx.replaceSurroundingText(location.hash);
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -2,6 +2,8 @@
|
||||
support-files =
|
||||
inputmethod_common.js
|
||||
file_test_app.html
|
||||
file_inputmethod.html
|
||||
|
||||
[test_basic.html]
|
||||
[test_bug944397.html]
|
||||
|
||||
|
89
dom/inputmethod/mochitest/test_bug944397.html
Normal file
89
dom/inputmethod/mochitest/test_bug944397.html
Normal file
@ -0,0 +1,89 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=944397
|
||||
-->
|
||||
<head>
|
||||
<title>Basic test for InputMethod API.</title>
|
||||
<script type="application/javascript;version=1.7" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=944397">Mozilla Bug 944397</a>
|
||||
<input type="text" />
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.7">
|
||||
|
||||
inputmethod_setup(function() {
|
||||
runTest();
|
||||
});
|
||||
|
||||
// The frame script running in file_test_app.html.
|
||||
function appFrameScript() {
|
||||
let input = content.document.getElementById('test-input');
|
||||
input.oninput = function() {
|
||||
sendAsyncMessage('test:InputMethod:oninput', {});
|
||||
};
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
var timeoutId = null;
|
||||
|
||||
// Create an app frame to recieve keyboard inputs.
|
||||
let app = document.createElement('iframe');
|
||||
app.src = 'file_test_app.html';
|
||||
app.setAttribute('mozbrowser', true);
|
||||
document.body.appendChild(app);
|
||||
app.addEventListener('mozbrowserloadend', function() {
|
||||
let mm = SpecialPowers.getBrowserFrameMessageManager(app);
|
||||
mm.loadFrameScript('data:,(' + appFrameScript.toString() + ')();', false);
|
||||
mm.addMessageListener("test:InputMethod:oninput", function() {
|
||||
ok(true, 'Keyboard input was received.');
|
||||
clearTimeout(timeoutId);
|
||||
inputmethod_cleanup();
|
||||
});
|
||||
});
|
||||
|
||||
// Create a browser frame to load the input method app.
|
||||
let keyboard = document.createElement('iframe');
|
||||
keyboard.setAttribute('mozbrowser', true);
|
||||
document.body.appendChild(keyboard);
|
||||
|
||||
let path = location.pathname;
|
||||
let imeUrl = location.protocol + '//' + location.host +
|
||||
path.substring(0, path.lastIndexOf('/')) +
|
||||
'/file_inputmethod.html#data';
|
||||
SpecialPowers.pushPermissions([{
|
||||
type: 'input',
|
||||
allow: true,
|
||||
context: imeUrl
|
||||
}], function() {
|
||||
let req = keyboard.setInputMethodActive(true);
|
||||
|
||||
req.onsuccess = function() {
|
||||
ok(true, 'setInputMethodActive succeeded.');
|
||||
timeoutId = setTimeout(function() {
|
||||
inputmethod_cleanup();
|
||||
ok(false, 'Failed to generate keyboard input.');
|
||||
}, 60000);
|
||||
};
|
||||
|
||||
req.onerror = function() {
|
||||
ok(false, 'setInputMethodActive failed: ' + this.error.name);
|
||||
inputmethod_cleanup();
|
||||
};
|
||||
|
||||
// Loads the input method app to the browser frame after a delay.
|
||||
setTimeout(function() {
|
||||
keyboard.src = imeUrl;
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -42,6 +42,10 @@ function debug(s) {
|
||||
dump("-*- RadioInterfaceLayer: " + s + "\n");
|
||||
}
|
||||
|
||||
// Ril quirk to attach data registration on demand.
|
||||
let RILQUIRKS_DATA_REGISTRATION_ON_DEMAND =
|
||||
libcutils.property_get("ro.moz.ril.data_reg_on_demand", "false") == "true";
|
||||
|
||||
const RADIOINTERFACELAYER_CID =
|
||||
Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
|
||||
const RADIOINTERFACE_CID =
|
||||
@ -690,6 +694,18 @@ function RadioInterfaceLayer() {
|
||||
options.clientId = clientId;
|
||||
this.radioInterfaces.push(new RadioInterface(options));
|
||||
}
|
||||
|
||||
// TODO: Move 'ril.data.*' settings handler to DataConnectionManager,
|
||||
// see bug 905568.
|
||||
let lock = gSettingsService.createLock();
|
||||
// Read the data enabled setting from DB.
|
||||
lock.get("ril.data.enabled", this);
|
||||
// Read the default client id for data call.
|
||||
lock.get("ril.data.defaultServiceId", this);
|
||||
|
||||
Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false);
|
||||
Services.obs.addObserver(this, kNetworkInterfaceStateChangedTopic, false);
|
||||
}
|
||||
RadioInterfaceLayer.prototype = {
|
||||
|
||||
@ -701,12 +717,171 @@ RadioInterfaceLayer.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRadioInterfaceLayer,
|
||||
Ci.nsIObserver]),
|
||||
|
||||
// Flag to determine the data state to start with when we boot up. It
|
||||
// corresponds to the 'ril.data.enabled' setting from the UI.
|
||||
_dataEnabled: null,
|
||||
|
||||
// Flag to record the default client id for data call. It
|
||||
// corresponds to the 'ril.data.defaultServiceId' setting from the UI.
|
||||
_dataDefaultClientId: -1,
|
||||
|
||||
// Flag to record the current default client id for data call.
|
||||
// It differs from _dataDefaultClientId in that it is set only when
|
||||
// the switch of client id process is done.
|
||||
_currentDataClientId: -1,
|
||||
|
||||
// Pending function to execute when we are notified that another data call has
|
||||
// been disconnected.
|
||||
_pendingDataCallRequest: null,
|
||||
|
||||
/**
|
||||
* nsIObserver interface methods.
|
||||
*/
|
||||
|
||||
observe: function observe(subject, topic, data) {
|
||||
// Nothing to do now. Just for profile-after-change.
|
||||
switch (topic) {
|
||||
case kMozSettingsChangedObserverTopic:
|
||||
let setting = JSON.parse(data);
|
||||
this.handle(setting.key, setting.value);
|
||||
break;
|
||||
case kNetworkInterfaceStateChangedTopic:
|
||||
let network = subject.QueryInterface(Ci.nsINetworkInterface);
|
||||
// DSDS: setup pending data connection when switching the default id
|
||||
// for data call. We can not use network.type to tell if it's
|
||||
// NETWORK_TYPE_MOBILE, since the type is removed from
|
||||
// RILNetworkInterface.connectedTypes on disconnect().
|
||||
if (network.state == Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN) {
|
||||
let oldRadioInterface =
|
||||
this.radioInterfaces[this._currentDataClientId];
|
||||
if (!oldRadioInterface.anyDataConnected() &&
|
||||
typeof this._pendingDataCallRequest === "function") {
|
||||
if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND) {
|
||||
oldRadioInterface.setDataRegistration(false);
|
||||
}
|
||||
if (DEBUG) debug("All data calls disconnected, setup pending data call.");
|
||||
this._pendingDataCallRequest();
|
||||
this._pendingDataCallRequest = null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NS_XPCOM_SHUTDOWN_OBSERVER_ID:
|
||||
Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
|
||||
Services.obs.removeObserver(this, kMozSettingsChangedObserverTopic);
|
||||
Services.obs.removeObserver(this, kNetworkInterfaceStateChangedTopic);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// nsISettingsServiceCallback
|
||||
|
||||
handle: function handle(name, result) {
|
||||
switch(name) {
|
||||
// TODO: Move 'ril.data.*' settings handler to DataConnectionManager,
|
||||
// see bug 905568.
|
||||
case "ril.data.enabled":
|
||||
if (DEBUG) debug("'ril.data.enabled' is now " + result);
|
||||
if (this._dataEnabled == result) {
|
||||
break;
|
||||
}
|
||||
this._dataEnabled = result;
|
||||
|
||||
if (DEBUG) debug("Default id for data call: " + this._dataDefaultClientId);
|
||||
if (this._dataDefaultClientId == -1) {
|
||||
// We haven't got the default id for data from db.
|
||||
break;
|
||||
}
|
||||
|
||||
let radioInterface = this.radioInterfaces[this._dataDefaultClientId];
|
||||
radioInterface.dataCallSettings.oldEnabled = radioInterface.dataCallSettings.enabled;
|
||||
radioInterface.dataCallSettings.enabled = result;
|
||||
radioInterface.updateRILNetworkInterface();
|
||||
break;
|
||||
case "ril.data.defaultServiceId":
|
||||
result = result ? result : 0;
|
||||
if (DEBUG) debug("'ril.data.defaultServiceId' is now " + result);
|
||||
if (this._dataDefaultClientId == result) {
|
||||
break;
|
||||
}
|
||||
this._dataDefaultClientId = result;
|
||||
this.handleDataClientIdChange();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
handleError: function handleError(errorMessage) {
|
||||
if (DEBUG) {
|
||||
debug("There was an error while reading RIL settings: " + errorMessage);
|
||||
}
|
||||
},
|
||||
|
||||
handleDataClientIdChange: function handleDataClientIdChange() {
|
||||
if (this._currentDataClientId == -1) {
|
||||
// This is to handle boot up stage.
|
||||
this._currentDataClientId = this._dataDefaultClientId;
|
||||
if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND) {
|
||||
let radioInterface = this.radioInterfaces[this._currentDataClientId];
|
||||
radioInterface.setDataRegistration(true);
|
||||
}
|
||||
if (this._dataEnabled) {
|
||||
let radioInterface = this.radioInterfaces[this._currentDataClientId];
|
||||
radioInterface.dataCallSettings.oldEnabled =
|
||||
radioInterface.dataCallSettings.enabled;
|
||||
radioInterface.dataCallSettings.enabled = true;
|
||||
radioInterface.updateRILNetworkInterface();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._dataEnabled) {
|
||||
if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND) {
|
||||
let oldRadioInterface = this.radioInterfaces[this._currentDataClientId];
|
||||
let newRadioInterface = this.radioInterfaces[this._dataDefaultClientId];
|
||||
oldRadioInterface.setDataRegistration(false);
|
||||
newRadioInterface.setDataRegistration(true);
|
||||
}
|
||||
this._currentDataClientId = this._dataDefaultClientId;
|
||||
return;
|
||||
}
|
||||
|
||||
let oldRadioInterface = this.radioInterfaces[this._currentDataClientId];
|
||||
oldRadioInterface.dataCallSettings.oldEnabled =
|
||||
oldRadioInterface.dataCallSettings.enabled;
|
||||
oldRadioInterface.dataCallSettings.enabled = false;
|
||||
|
||||
if (oldRadioInterface.anyDataConnected()) {
|
||||
this._pendingDataCallRequest = function () {
|
||||
if (DEBUG) debug("Executing pending data call request.");
|
||||
let newRadioInterface = this.radioInterfaces[this._dataDefaultClientId];
|
||||
if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND) {
|
||||
newRadioInterface.setDataRegistration(true);
|
||||
}
|
||||
newRadioInterface.dataCallSettings.oldEnabled =
|
||||
newRadioInterface.dataCallSettings.enabled;
|
||||
newRadioInterface.dataCallSettings.enabled = this._dataEnabled;
|
||||
|
||||
this._currentDataClientId = this._dataDefaultClientId;
|
||||
newRadioInterface.updateRILNetworkInterface();
|
||||
};
|
||||
|
||||
if (DEBUG) {
|
||||
debug("handleDataClientIdChange: existing data call(s) active,"
|
||||
+ " wait for them to get disconnected.");
|
||||
}
|
||||
oldRadioInterface.deactivateDataCalls();
|
||||
return;
|
||||
}
|
||||
|
||||
let newRadioInterface = this.radioInterfaces[this._dataDefaultClientId];
|
||||
newRadioInterface.dataCallSettings.oldEnabled =
|
||||
newRadioInterface.dataCallSettings.enabled;
|
||||
newRadioInterface.dataCallSettings.enabled = true;
|
||||
|
||||
this._currentDataClientId = this._dataDefaultClientId;
|
||||
if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND) {
|
||||
oldRadioInterface.setDataRegistration(false);
|
||||
newRadioInterface.setDataRegistration(true);
|
||||
}
|
||||
newRadioInterface.updateRILNetworkInterface();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -942,12 +1117,8 @@ function RadioInterface(options) {
|
||||
|
||||
// Read the APN data from the settings DB.
|
||||
lock.get("ril.data.roaming_enabled", this);
|
||||
lock.get("ril.data.enabled", this);
|
||||
lock.get("ril.data.apnSettings", this);
|
||||
|
||||
// Read the default client id for data call.
|
||||
lock.get("ril.data.defaultServiceId", this);
|
||||
|
||||
// Read the "time.clock.automatic-update.enabled" setting to see if
|
||||
// we need to adjust the system clock time by NITZ or SNTP.
|
||||
lock.get(kSettingsClockAutoUpdateEnabled, this);
|
||||
@ -1801,6 +1972,18 @@ RadioInterface.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
anyDataConnected: function anyDataConnected() {
|
||||
for each (let apnSetting in this.apnSettings.byApn) {
|
||||
for each (let type in apnSetting.types) {
|
||||
if (this.getDataCallStateByType(type) ==
|
||||
RIL.GECKO_NETWORK_STATE_CONNECTED) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if we get all necessary APN data.
|
||||
*/
|
||||
@ -1811,32 +1994,8 @@ RadioInterface.prototype = {
|
||||
apnSetting.types.length);
|
||||
},
|
||||
|
||||
handleDataClientIdChange: function handleDataClientIdChange() {
|
||||
// Default data has been switched to the current RadioInterface.
|
||||
// If there is an active default data call, wait for it to get
|
||||
// disconnected, otherwise connect directly.
|
||||
if (this.clientId == this._dataDefaultClientId &&
|
||||
this._dataEnabled) {
|
||||
this.dataCallSettings.oldEnabled = this.dataCallSettings.enabled;
|
||||
this.dataCallSettings.enabled = true;
|
||||
if (gNetworkManager.active &&
|
||||
gNetworkManager.active.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
|
||||
if (DEBUG) this.debug("Default data active, wait for it to get disconnected.");
|
||||
this._dataCallSetupPending = true;
|
||||
return;
|
||||
}
|
||||
this.updateRILNetworkInterface();
|
||||
return;
|
||||
}
|
||||
|
||||
// Default data has been switched from this current RadioInterface,
|
||||
// disconnet data call if it is enabled.
|
||||
if (this.clientId != this._dataDefaultClientId &&
|
||||
this.dataCallSettings.enabled) {
|
||||
this.dataCallSettings.oldEnabled = this.dataCallSettings.enabled;
|
||||
this.dataCallSettings.enabled = false;
|
||||
this.updateRILNetworkInterface();
|
||||
}
|
||||
setDataRegistration: function setDataRegistration(attach) {
|
||||
this.workerMessenger.send("setDataRegistration", {attach: attach});
|
||||
},
|
||||
|
||||
updateRILNetworkInterface: function updateRILNetworkInterface() {
|
||||
@ -2471,18 +2630,6 @@ RadioInterface.prototype = {
|
||||
this._sntp.request();
|
||||
}
|
||||
}
|
||||
|
||||
// DSDS: setup pending data connection when switching the default id
|
||||
// for data call.
|
||||
// We can not use network.type to tell if it's NETWORK_TYPE_MOBILE,
|
||||
// since the type is removed from RILNetworkInterface.connectedTypes
|
||||
// on disconnect().
|
||||
if (network.state == Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN &&
|
||||
this._dataCallSetupPending) {
|
||||
if (DEBUG) this.debug("Default data disconnected, setup pending data call.");
|
||||
this._dataCallSetupPending = false;
|
||||
this.updateRILNetworkInterface();
|
||||
}
|
||||
break;
|
||||
case kScreenStateChangedTopic:
|
||||
this.workerMessenger.send("setScreenState", { on: (data === "on") });
|
||||
@ -2495,17 +2642,6 @@ RadioInterface.prototype = {
|
||||
|
||||
apnSettings: null,
|
||||
|
||||
// Flag to determine the data state to start with when we boot up. It
|
||||
// corresponds to the 'ril.data.enabled' setting from the UI.
|
||||
_dataEnabled: null,
|
||||
|
||||
// Flag to record the default client id for data call.
|
||||
_dataDefaultClientId: null,
|
||||
|
||||
// Flag to determine if we need to setup data call when we are notified
|
||||
// that another data call has been disconnected.
|
||||
_dataCallSetupPending: false,
|
||||
|
||||
// Flag to determine whether to update system clock automatically. It
|
||||
// corresponds to the "time.clock.automatic-update.enabled" setting.
|
||||
_clockAutoUpdateEnabled: null,
|
||||
@ -2565,19 +2701,6 @@ RadioInterface.prototype = {
|
||||
if (DEBUG) this.debug("'ril.radio.preferredNetworkType' is now " + aResult);
|
||||
this.setPreferredNetworkTypeBySetting(aResult);
|
||||
break;
|
||||
case "ril.data.enabled":
|
||||
if (DEBUG) this.debug("'ril.data.enabled' is now " + aResult);
|
||||
if (this._dataEnabled == aResult) {
|
||||
break;
|
||||
}
|
||||
this._dataEnabled = aResult;
|
||||
if (this.clientId != this._dataDefaultClientId) {
|
||||
break;
|
||||
}
|
||||
this.dataCallSettings.oldEnabled = this.dataCallSettings.enabled;
|
||||
this.dataCallSettings.enabled = aResult;
|
||||
this.updateRILNetworkInterface();
|
||||
break;
|
||||
case "ril.data.roaming_enabled":
|
||||
if (DEBUG) this.debug("'ril.data.roaming_enabled' is now " + aResult);
|
||||
this.dataCallSettings.roamingEnabled = aResult;
|
||||
@ -2590,15 +2713,6 @@ RadioInterface.prototype = {
|
||||
this.updateRILNetworkInterface();
|
||||
}
|
||||
break;
|
||||
case "ril.data.defaultServiceId":
|
||||
aResult = aResult ? aResult : 0;
|
||||
if (DEBUG) this.debug("'ril.data.defaultServiceId' is now " + aResult);
|
||||
if (this._dataDefaultClientId == aResult) {
|
||||
break;
|
||||
}
|
||||
this._dataDefaultClientId = aResult;
|
||||
this.handleDataClientIdChange();
|
||||
break;
|
||||
case kSettingsClockAutoUpdateEnabled:
|
||||
this._clockAutoUpdateEnabled = aResult;
|
||||
if (!this._clockAutoUpdateEnabled) {
|
||||
|
@ -152,6 +152,10 @@ this.REQUEST_MODIFY_QOS = 118;
|
||||
this.REQUEST_SUSPEND_QOS = 119;
|
||||
this.REQUEST_RESUME_QOS = 120;
|
||||
|
||||
// Fugu specific parcel types.
|
||||
this.RIL_REQUEST_GPRS_ATTACH = 5018;
|
||||
this.RIL_REQUEST_GPRS_DETACH = 5019;
|
||||
|
||||
// UICC Secure Access
|
||||
this.REQUEST_SIM_OPEN_CHANNEL = 121;
|
||||
this.REQUEST_SIM_CLOSE_CHANNEL = 122;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user