merge m-c to fx-team

This commit is contained in:
Tim Taubert 2013-08-25 15:10:36 +02:00
commit 3c154f8697
49 changed files with 658 additions and 402 deletions

View File

@ -48,6 +48,7 @@ if (Services.prefs.getBoolPref("browser.tabs.remote")) {
});
addEventListener("DOMFormHasPassword", function(event) {
InsecurePasswordUtils.checkForInsecurePasswords(event.target);
LoginManagerContent.onFormPassword(event);
});
addEventListener("DOMAutoComplete", function(event) {
LoginManagerContent.onUsernameInput(event);

View File

@ -543,7 +543,7 @@ BrowserGlue.prototype = {
label: win.gNavigatorBundle.getString("slowStartup.helpButton.label"),
accessKey: win.gNavigatorBundle.getString("slowStartup.helpButton.accesskey"),
callback: function () {
win.openUILinkIn("https://support.mozilla.org/kb/firefox-takes-long-time-start-up", "tab");
win.openUILinkIn("https://support.mozilla.org/kb/reset-firefox-easily-fix-most-problems", "tab");
}
},
{

View File

@ -12,7 +12,7 @@ let Services = tempScope.Services;
// Disable logging for faster test runs. Set this pref to true if you want to
// debug a test in your try runs.
let gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log");
Services.prefs.setBoolPref("devtools.debugger.log", true);
Services.prefs.setBoolPref("devtools.debugger.log", false);
Cu.import("resource://gre/modules/devtools/dbg-server.jsm", tempScope);
Cu.import("resource://gre/modules/devtools/dbg-client.jsm", tempScope);

View File

@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Components.utils.import("resource:///modules/ContentUtil.jsm");
let Util = {
/*
* General purpose utilities
@ -11,70 +13,12 @@ let Util = {
return aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
},
// Recursively find all documents, including root document.
getAllDocuments: function getAllDocuments(doc, resultSoFar) {
resultSoFar = resultSoFar || [doc];
if (!doc.defaultView)
return resultSoFar;
let frames = doc.defaultView.frames;
if (!frames)
return resultSoFar;
let i;
let currentDoc;
for (i = 0; i < frames.length; i++) {
currentDoc = frames[i].document;
resultSoFar.push(currentDoc);
this.getAllDocuments(currentDoc, resultSoFar);
}
return resultSoFar;
},
// Put the Mozilla networking code into a state that will kick the
// auto-connection process.
forceOnline: function forceOnline() {
Services.io.offline = false;
},
// Pass several objects in and it will combine them all into the first object and return it.
// NOTE: Deep copy is not supported
extend: function extend() {
// copy reference to target object
let target = arguments[0] || {};
let length = arguments.length;
if (length === 1) {
return target;
}
// Handle case when target is a string or something
if (typeof target != "object" && typeof target != "function") {
target = {};
}
for (let i = 1; i < length; i++) {
// Only deal with non-null/undefined values
let options = arguments[i];
if (options != null) {
// Extend the base object
for (let name in options) {
let copy = options[name];
// Prevent never-ending loop
if (target === copy)
continue;
if (copy !== undefined)
target[name] = copy;
}
}
}
// Return the modified object
return target;
},
/*
* Timing utilties
*/
@ -92,17 +36,6 @@ let Util = {
* Console printing utilities
*/
dumpf: function dumpf(str) {
let args = arguments;
let i = 1;
dump(str.replace(/%s/g, function() {
if (i >= args.length) {
throw "dumps received too many placeholders and not enough arguments";
}
return args[i++].toString();
}));
},
// Like dump, but each arg is handled and there's an automatic newline
dumpLn: function dumpLn() {
for (let i = 0; i < arguments.length; i++)
@ -110,30 +43,10 @@ let Util = {
dump("\n");
},
dumpElement: function dumpElement(aElement) {
this.dumpLn(aElement.id);
},
dumpElementTree: function dumpElementTree(aElement) {
let node = aElement;
while (node) {
this.dumpLn("node:", node, "id:", node.id, "class:", node.classList);
node = node.parentNode;
}
},
/*
* Element utilities
*/
highlightElement: function highlightElement(aElement) {
if (aElement == null) {
this.dumpLn("aElement is null");
return;
}
aElement.style.border = "2px solid red";
},
transitionElementVisibility: function(aNodes, aVisible) {
// accept single node or a collection of nodes
aNodes = aNodes.length ? aNodes : [aNodes];
@ -161,24 +74,6 @@ let Util = {
return defd.promise;
},
getHrefForElement: function getHrefForElement(target) {
let link = null;
while (target) {
if (target instanceof Ci.nsIDOMHTMLAnchorElement ||
target instanceof Ci.nsIDOMHTMLAreaElement ||
target instanceof Ci.nsIDOMHTMLLinkElement) {
if (target.hasAttribute("href"))
link = target;
}
target = target.parentNode;
}
if (link && link.hasAttribute("href"))
return link.href;
else
return null;
},
isTextInput: function isTextInput(aElement) {
return ((aElement instanceof Ci.nsIDOMHTMLInputElement &&
aElement.mozIsTextField(false)) ||
@ -308,16 +203,6 @@ let Util = {
aURL.indexOf("chrome:") == 0);
},
isOpenableScheme: function isShareableScheme(aProtocol) {
let dontOpen = /^(mailto|javascript|news|snews)$/;
return (aProtocol && !dontOpen.test(aProtocol));
},
isShareableScheme: function isShareableScheme(aProtocol) {
let dontShare = /^(chrome|about|file|javascript|resource)$/;
return (aProtocol && !dontShare.test(aProtocol));
},
// Don't display anything in the urlbar for these special URIs.
isURLEmpty: function isURLEmpty(aURL) {
return (!aURL ||
@ -382,68 +267,6 @@ let Util = {
return this.displayDPI = this.getWindowUtils(window).displayDPI;
},
isPortrait: function isPortrait() {
return (window.innerWidth <= window.innerHeight);
},
LOCALE_DIR_RTL: -1,
LOCALE_DIR_LTR: 1,
get localeDir() {
// determine browser dir first to know which direction to snap to
let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry);
return chromeReg.isLocaleRTL("global") ? this.LOCALE_DIR_RTL : this.LOCALE_DIR_LTR;
},
/*
* Process utilities
*/
isParentProcess: function isInParentProcess() {
let appInfo = Cc["@mozilla.org/xre/app-info;1"];
return (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT);
},
/*
* Event utilities
*/
modifierMaskFromEvent: function modifierMaskFromEvent(aEvent) {
return (aEvent.altKey ? Ci.nsIDOMEvent.ALT_MASK : 0) |
(aEvent.ctrlKey ? Ci.nsIDOMEvent.CONTROL_MASK : 0) |
(aEvent.shiftKey ? Ci.nsIDOMEvent.SHIFT_MASK : 0) |
(aEvent.metaKey ? Ci.nsIDOMEvent.META_MASK : 0);
},
/*
* Download utilities
*/
insertDownload: function insertDownload(aSrcUri, aFile) {
let dm = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager);
let db = dm.DBConnection;
let stmt = db.createStatement(
"INSERT INTO moz_downloads (name, source, target, startTime, endTime, state, referrer) " +
"VALUES (:name, :source, :target, :startTime, :endTime, :state, :referrer)"
);
stmt.params.name = aFile.leafName;
stmt.params.source = aSrcUri.spec;
stmt.params.target = aFile.path;
stmt.params.startTime = Date.now() * 1000;
stmt.params.endTime = Date.now() * 1000;
stmt.params.state = Ci.nsIDownloadManager.DOWNLOAD_NOTSTARTED;
stmt.params.referrer = aSrcUri.spec;
stmt.execute();
stmt.finalize();
let newItemId = db.lastInsertRowID;
let download = dm.getDownload(newItemId);
//dm.resumeDownload(download);
//Services.obs.notifyObservers(download, "dl-start", null);
},
/*
* Local system utilities
*/
@ -540,3 +363,11 @@ Util.Timeout.prototype = {
}
};
// Mixin the ContentUtil module exports
{
for (let name in ContentUtil) {
let copy = ContentUtil[name];
if (copy !== undefined)
Util[name] = copy;
}
}

View File

@ -1096,14 +1096,6 @@ var BrowserUI = {
case "cmd_panel":
PanelUI.toggle();
break;
case "cmd_volumeLeft":
// Zoom in (portrait) or out (landscape)
Browser.zoom(Util.isPortrait() ? -1 : 1);
break;
case "cmd_volumeRight":
// Zoom out (portrait) or in (landscape)
Browser.zoom(Util.isPortrait() ? 1 : -1);
break;
case "cmd_openFile":
this.openFile();
break;

View File

@ -95,12 +95,6 @@
<command id="cmd_sanitize" oncommand="CommandUpdater.doCommand(this.id);"/>
<command id="cmd_contextUI" oncommand="CommandUpdater.doCommand(this.id);"/>
<!-- screen/display -->
<command id="cmd_lockscreen" oncommand="CommandUpdater.doCommand(this.id);"/>
<command id="cmd_volumeLeft" observes="bcast_contentShowing" oncommand="CommandUpdater.doCommand(this.id);"/>
<command id="cmd_volumeRight" observes="bcast_contentShowing" oncommand="CommandUpdater.doCommand(this.id);"/>
<!-- scrolling -->
<command id="cmd_scrollPageUp" oncommand="CommandUpdater.doCommand(this.id);"/>
<command id="cmd_scrollPageDown" oncommand="CommandUpdater.doCommand(this.id);"/>

View File

@ -140,6 +140,7 @@ let Content = {
addEventListener("MozApplicationManifest", this, false);
addEventListener("DOMContentLoaded", this, false);
addEventListener("DOMAutoComplete", this, false);
addEventListener("DOMFormHasPassword", this, false);
addEventListener("blur", this, false);
addEventListener("pagehide", this, false);
// Attach a listener to watch for "click" events bubbling up from error
@ -189,6 +190,10 @@ let Content = {
this._onClickCapture(aEvent);
break;
case "DOMFormHasPassword":
LoginManagerContent.onFormPassword(aEvent);
break;
case "DOMContentLoaded":
LoginManagerContent.onContentLoaded(aEvent);
this._maybeNotifyErrorPage();

View File

@ -140,13 +140,13 @@ var FindHelperUI = {
this._container.removeEventListener("transitionend", onTransitionEnd, true);
this._textbox.value = "";
this.status = null;
this._textbox.blur();
this._open = false;
// Restore the scroll synchronisation
Browser.selectedBrowser.scrollSync = true;
};
this._textbox.blur();
this._container.addEventListener("transitionend", onTransitionEnd, true);
this._container.dismiss();
Elements.browsers.removeAttribute("findbar");

View File

@ -0,0 +1,5 @@
<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" xml:lang="en">
<body>
</body>
</html>

View File

@ -1,10 +1,10 @@
"use strict";
load('Util.js');
load("Util.js");
function run_test() {
do_print("Testing Util.extend");
do_print("Check if function is defined");
do_check_true(!!Util.extend);
@ -14,7 +14,7 @@ function run_test() {
let nullRes = Util.extend(null);
do_check_true(nullRes && typeof nullRes == "object");
do_print("Simple extend");
let simpleExtend = {a: 1, b: 2};
let simpleExtendResult = Util.extend(simpleExtend, {b: 3, c: 4});

View File

@ -0,0 +1,90 @@
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
/* 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";
let Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/ContentUtil.jsm");
load("Util.js");
function empty_node(node) {
let cnode;
while((cnode = node.firstChild))
node.removeChild(cnode);
return node;
}
function DOMSerializer() {
return Components.classes["@mozilla.org/xmlextras/xmlserializer;1"]
.createInstance(Components.interfaces.nsIDOMSerializer);
}
function serializeContents(node) {
let str = DOMSerializer().serializeToString(node);
return str.replace(/^<[^>]+>/, '')
.replace(/<\/[^>]+>$/, '');
}
function run_test() {
let doc, body, str, expectedResult, frag;
do_print("Testing Util.populateFragmentFromString");
do_check_true(!!Util.populateFragmentFromString);
do_check_true(!!ContentUtil.populateFragmentFromString);
do_check_eq(ContentUtil.populateFragmentFromString, Util.populateFragmentFromString);
do_print("Loading blank document");
doc = do_parse_document("blank.xhtml", "application/xhtml+xml");
// sanity check
do_check_eq(doc.nodeType, 9);
do_check_true(doc.documentElement.localName != "parsererror");
body = doc.documentElement.getElementsByTagName("body")[0];
do_check_eq(1, body.nodeType);
frag = doc.createDocumentFragment();
// test proper handling of leading and trailing text
str = "Before, #2, #1. After";
Util.populateFragmentFromString(
frag, str,
{ text: "One", className: "text-one"},
{ text: "Two", className: "text-two"}
);
empty_node(body);
body.appendChild(frag);
expectedResult = 'Before, <span class="text-two">Two</span>, <span class="text-one">One</span>. After';
do_check_eq(serializeContents(body), expectedResult);
// test proper handling of unspecified markers
str = "#8080: #1. http://localhost/#bar";
Util.populateFragmentFromString(
frag, str,
{ text: "One" }
);
empty_node(body);
body.appendChild(frag);
expectedResult = '#8080: <span>One</span>. http://localhost/#bar';
do_check_eq(serializeContents(body), expectedResult);
// test proper handling of markup in strings
str = "#1 <body> tag. &copy; 2000 - Some Corp\u2122";
Util.populateFragmentFromString(
frag, str,
{ text: "About the" }
);
empty_node(body);
body.appendChild(frag);
expectedResult = "<span>About the</span> &lt;body&gt; tag. &amp;copy; 2000 - Some Corp™"
do_check_eq(serializeContents(body), expectedResult);
}

View File

@ -1,5 +1,8 @@
[DEFAULT]
head =
head =
tail =
firefox-appdir = metro
[test_util_extend.js]
[test_util_populateFragmentFromString.js]

View File

@ -14,6 +14,11 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/DownloadUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "ContentUtil", function() {
Cu.import("resource:///modules/ContentUtil.jsm");
return ContentUtil;
});
// -----------------------------------------------------------------------
// HelperApp Launcher Dialog
// -----------------------------------------------------------------------
@ -97,19 +102,35 @@ HelperAppLauncherDialog.prototype = {
let window = Services.wm.getMostRecentWindow("navigator:browser");
let chromeWin = this._getChromeWindow(window).wrappedJSObject;
let notificationBox = chromeWin.Browser.getNotificationBox();
let document = notificationBox.ownerDocument;
downloadSize = this._getDownloadSize(aLauncher.contentLength);
let msg = browserBundle.GetStringFromName("alertDownloadSave")
.replace("#1", aLauncher.suggestedFileName)
.replace("#2", downloadSize)
.replace("#3", aLauncher.source.host);
let msg = browserBundle.GetStringFromName("alertDownloadSave");
let fragment = ContentUtil.populateFragmentFromString(
document.createDocumentFragment(),
msg,
{
text: aLauncher.suggestedFileName,
className: "download-filename-text"
},
{
text: aLauncher.suggestedFileName,
className: "download-size-text"
},
{
text: aLauncher.source.host,
className: "download-host-text"
}
);
notificationBox.notificationsHidden = false;
let newBar = notificationBox.appendNotification(msg,
let newBar = notificationBox.appendNotification("",
"save-download",
URI_GENERIC_ICON_DOWNLOAD,
notificationBox.PRIORITY_WARNING_HIGH,
buttons);
let messageContainer = document.getAnonymousElementByAttribute(newBar, "anonid", "messageText");
messageContainer.appendChild(fragment);
},
promptForSaveToFile: function hald_promptForSaveToFile(aLauncher, aContext, aDefaultFile, aSuggestedFileExt, aForcePrompt) {

View File

@ -0,0 +1,92 @@
/* 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";
this.EXPORTED_SYMBOLS = ["ContentUtil"];
const XHTML_NS = "http://www.w3.org/1999/xhtml";
this.ContentUtil = {
populateFragmentFromString: function populateFragmentFromString(fragment, str) {
let re = /^([^#]*)#(\d+)\b([^#]*)/,
document = fragment.ownerDocument,
// the remaining arguments are our {text, className} values
replacements = Array.slice(arguments, 2),
match;
// walk over the string, building textNode/spans as nec. with replacement content
// note that #1,#2 etc. may not appear in numerical order in the string
while ((match = re.exec(str))) {
let [mstring,pre,num,post] = match,
replaceText = "",
replaceClass,
idx = num-1; // markers are 1-based, replacement indices 0 based
str = str.substring(re.lastIndex+mstring.length);
if (pre)
fragment.appendChild(document.createTextNode(pre));
if (replacements[idx]) {
replaceText = replacements[idx].text;
let spanNode = document.createElementNS(XHTML_NS, "span");
spanNode.appendChild(document.createTextNode(replaceText));
// add class to the span when provided
if(replacements[idx].className)
spanNode.classList.add(replacements[idx].className);
fragment.appendChild(spanNode);
} else {
// put it back if no replacement was provided
fragment.appendChild(document.createTextNode("#"+num));
}
if(post)
fragment.appendChild(document.createTextNode(post));
}
if(str)
fragment.appendChild(document.createTextNode(str));
return fragment;
},
// Pass several objects in and it will combine them all into the first object and return it.
// NOTE: Deep copy is not supported
extend: function extend() {
// copy reference to target object
let target = arguments[0] || {};
let length = arguments.length;
if (length === 1) {
return target;
}
// Handle case when target is a string or something
if (typeof target != "object" && typeof target != "function") {
target = {};
}
for (let i = 1; i < length; i++) {
// Only deal with non-null/undefined values
let options = arguments[i];
if (options != null) {
// Extend the base object
for (let name in options) {
let copy = options[name];
// Prevent never-ending loop
if (target === copy)
continue;
if (copy !== undefined)
target[name] = copy;
}
}
}
// Return the modified object
return target;
}
};

View File

@ -5,6 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXTRA_JS_MODULES += [
'ContentUtil.jsm',
'CrossSlide.jsm',
'View.jsm',
'colorUtils.jsm',

View File

@ -696,7 +696,7 @@ documenttab[selected] .documenttab-selection {
}
/* navbar edit button: one button out of three - when editing: go, when !editing,
loading: stop, when !editing, !loading: reload */
loading: stop, when !editing, !loading: reload */
#go-button, #reload-button, #stop-button {
visibility: collapse;
@ -1006,6 +1006,15 @@ documenttab[selected] .documenttab-selection {
-moz-image-region: rect(80px, 560px, 120px, 520px) !important;
}
/* Download notifications ======================================================= */
.download-filename-text {
font-weight: bold;
}
.download-host-text {
font-weight: bold;
}
/* Autoscroll popup ======================================================== */
.autoscroller {

View File

@ -37,7 +37,11 @@
transition: opacity .15s ease 0s;
}
.side-menu-widget-item-checkbox > .checkbox-check {
.side-menu-widget-item-checkbox > .checkbox-spacer-box {
-moz-appearance: none;
}
.side-menu-widget-item-checkbox > .checkbox-spacer-box > .checkbox-check {
-moz-appearance: none;
background: none;
background-image: url(itemToggle.png);
@ -50,7 +54,7 @@
border: 0;
}
.side-menu-widget-item-checkbox[checked] > .checkbox-check {
.side-menu-widget-item-checkbox[checked] > .checkbox-spacer-box > .checkbox-check {
background-position: 0 0;
}

View File

@ -1664,12 +1664,11 @@ abstract public class GeckoApp
protected int getSessionRestoreState(Bundle savedInstanceState) {
final SharedPreferences prefs = GeckoApp.getAppSharedPreferences();
int restoreMode = RESTORE_NONE;
boolean allowCrashRestore = true;
// If the version has changed, the user has done an upgrade, so restore
// previous tabs.
final int versionCode = getVersionCode();
if (prefs.getInt(PREFS_VERSION_CODE, 0) != versionCode) {
// If the version has changed, the user has done an upgrade, so restore
// previous tabs.
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
public void run() {
@ -1680,19 +1679,12 @@ abstract public class GeckoApp
});
restoreMode = RESTORE_NORMAL;
} else if (savedInstanceState != null) {
} else if (savedInstanceState != null || PreferenceManager.getDefaultSharedPreferences(this)
.getString(GeckoPreferences.PREFS_RESTORE_SESSION, "quit")
.equals("always")) {
// We're coming back from a background kill by the OS or the user
// has chosen to always restore, so restore.
restoreMode = RESTORE_NORMAL;
} else {
String restorePref = PreferenceManager.getDefaultSharedPreferences(this)
.getString(GeckoPreferences.PREFS_RESTORE_SESSION, "crash");
if ("always".equals(restorePref)) {
restoreMode = RESTORE_NORMAL;
} else {
restoreMode = RESTORE_NONE;
if ("never".equals(restorePref)) {
allowCrashRestore = false;
}
}
}
// We record crashes in the crash reporter. If sessionstore.js
@ -1709,9 +1701,7 @@ abstract public class GeckoApp
}
});
if (allowCrashRestore) {
restoreMode = RESTORE_CRASH;
}
restoreMode = RESTORE_CRASH;
}
return restoreMode;

View File

@ -77,7 +77,7 @@ public class GeckoPreferences
private static String PREFS_HEALTHREPORT_LINK = NON_PREF_PREFIX + "healthreport.link";
private static String PREFS_DEVTOOLS_REMOTE_ENABLED = "devtools.debugger.remote-enabled";
public static String PREFS_RESTORE_SESSION = NON_PREF_PREFIX + "restoreSession2";
public static String PREFS_RESTORE_SESSION = NON_PREF_PREFIX + "restoreSession3";
// These values are chosen to be distinct from other Activity constants.
private static int REQUEST_CODE_PREF_SCREEN = 5;

View File

@ -668,6 +668,7 @@ RES_DRAWABLE_MDPI = \
res/drawable-mdpi/icon_most_recent_empty.png \
res/drawable-mdpi/icon_most_visited.png \
res/drawable-mdpi/icon_most_visited_empty.png \
res/drawable-mdpi/icon_openinapp.png \
res/drawable-mdpi/icon_pageaction.png \
res/drawable-mdpi/icon_reading_list_empty.png \
res/drawable-mdpi/progress_spinner.png \
@ -780,6 +781,7 @@ RES_DRAWABLE_HDPI = \
res/drawable-hdpi/icon_most_recent_empty.png \
res/drawable-hdpi/icon_most_visited.png \
res/drawable-hdpi/icon_most_visited_empty.png \
res/drawable-hdpi/icon_openinapp.png \
res/drawable-hdpi/icon_pageaction.png \
res/drawable-hdpi/icon_reading_list_empty.png \
res/drawable-hdpi/tab_indicator_divider.9.png \
@ -878,6 +880,7 @@ RES_DRAWABLE_XHDPI = \
res/drawable-xhdpi/icon_most_recent_empty.png \
res/drawable-xhdpi/icon_most_visited.png \
res/drawable-xhdpi/icon_most_visited_empty.png \
res/drawable-xhdpi/icon_openinapp.png \
res/drawable-xhdpi/icon_pageaction.png \
res/drawable-xhdpi/icon_reading_list_empty.png \
res/drawable-xhdpi/spinner_default.9.png \

View File

@ -407,11 +407,16 @@ public class BrowserDB {
public boolean moveToPosition(int position) {
mIndex = position;
// move the real cursor as if we were stepping through it to this position
// be careful not to move it to far, and to account for any pinned sites
// Move the real cursor as if we were stepping through it to this position.
// Account for pinned sites, and be careful to update its position to the
// minimum or maximum position, even if we're moving beyond its bounds.
int before = getPinnedBefore(position);
int p2 = position - before;
if (p2 >= -1 && p2 <= mCursor.getCount()) {
if (p2 <= -1) {
super.moveToPosition(-1);
} else if (p2 >= mCursor.getCount()) {
super.moveToPosition(mCursor.getCount());
} else {
super.moveToPosition(p2);
}

View File

@ -112,8 +112,7 @@
<!ENTITY pref_reflow_on_zoom4 "Text reflow">
<!ENTITY pref_restore "Tabs">
<!ENTITY pref_restore_always "Always restore">
<!ENTITY pref_restore_crash "Restore after a crash">
<!ENTITY pref_restore_never "Never restore">
<!ENTITY pref_restore_quit "Don\'t restore after quitting &brandShortName;">
<!ENTITY pref_font_size_tiny "Tiny">
<!ENTITY pref_font_size_small "Small">
<!ENTITY pref_font_size_medium "Medium">

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 B

View File

@ -101,13 +101,11 @@
</string-array>
<string-array name="pref_restore_entries">
<item>@string/pref_restore_always</item>
<item>@string/pref_restore_crash</item>
<item>@string/pref_restore_never</item>
<item>@string/pref_restore_quit</item>
</string-array>
<string-array name="pref_restore_values">
<item>always</item>
<item>crash</item>
<item>never</item>
<item>quit</item>
</string-array>
<string-array name="pref_update_autodownload_entries">
<item>@string/pref_update_autodownload_enabled</item>

View File

@ -25,9 +25,9 @@
android:negativeButtonText="@string/button_cancel"
android:persistent="false" />
<ListPreference android:key="android.not_a_preference.restoreSession2"
<ListPreference android:key="android.not_a_preference.restoreSession3"
android:title="@string/pref_restore"
android:defaultValue="crash"
android:defaultValue="quit"
android:entries="@array/pref_restore_entries"
android:entryValues="@array/pref_restore_values"
android:persistent="true" />

View File

@ -31,9 +31,9 @@
android:negativeButtonText="@string/button_cancel"
android:persistent="false" />
<ListPreference android:key="android.not_a_preference.restoreSession2"
<ListPreference android:key="android.not_a_preference.restoreSession3"
android:title="@string/pref_restore"
android:defaultValue="crash"
android:defaultValue="quit"
android:entries="@array/pref_restore_entries"
android:entryValues="@array/pref_restore_values"
android:persistent="true" />

View File

@ -27,9 +27,9 @@
android:negativeButtonText="@string/button_cancel"
android:persistent="false" />
<ListPreference android:key="android.not_a_preference.restoreSession2"
<ListPreference android:key="android.not_a_preference.restoreSession3"
android:title="@string/pref_restore"
android:defaultValue="crash"
android:defaultValue="quit"
android:entries="@array/pref_restore_entries"
android:entryValues="@array/pref_restore_values"
android:persistent="true" />

View File

@ -129,8 +129,7 @@
<string name="pref_reflow_on_zoom">&pref_reflow_on_zoom4;</string>
<string name="pref_restore">&pref_restore;</string>
<string name="pref_restore_always">&pref_restore_always;</string>
<string name="pref_restore_crash">&pref_restore_crash;</string>
<string name="pref_restore_never">&pref_restore_never;</string>
<string name="pref_restore_quit">&pref_restore_quit;</string>
<string name="pref_show_product_announcements">&pref_show_product_announcements;</string>
<string name="pref_sync">&pref_sync;</string>
<string name="pref_search_suggestions">&pref_search_suggestions;</string>

View File

@ -26,7 +26,7 @@ public class testSettingsMenuItems extends PixelTest {
String[][] OPTIONS_CUSTOMIZE = {
{ "Search settings", "", "Show search suggestions", "Installed search engines" },
{ "Import from Android", "", "Bookmarks", "History", "Import" },
{ "Tabs", "Restore after a crash", "Always restore", "Restore after a crash", "Never restore" },
{ "Tabs", "Don't restore after quitting " + BRAND_NAME, "Always restore", "Don't restore after quitting " + BRAND_NAME },
{ "Automatic updates", "Only over Wi-Fi", "Enabled", "Only over Wi-Fi", "Disabled" },
};

View File

@ -69,6 +69,54 @@ var HelperApps = {
return found;
},
updatePageAction: function setPageAction(uri) {
let apps = this.getAppsForUri(uri);
if (apps.length > 0)
this._setPageActionFor(uri, apps);
else
this._removePageAction();
},
_setPageActionFor: function setPageActionFor(uri, apps) {
this._pageActionUri = uri;
// If the pageaction is already added, simply update the URI to be launched when 'onclick' is triggered.
if (this._pageActionId != undefined)
return;
this._pageActionId = NativeWindow.pageactions.add({
title: Strings.browser.GetStringFromName("openInApp.pageAction"),
icon: "drawable://icon_openinapp",
clickCallback: function() {
if (apps.length == 1)
this._launchApp(apps[0], this._pageActionUri);
else
this.openUriInApp(this._pageActionUri);
}.bind(this)
});
},
_removePageAction: function removePageAction() {
if(!this._pageActionId)
return;
NativeWindow.pageactions.remove(this._pageActionId);
delete this._pageActionId;
},
_launchApp: function launchApp(appData, uri) {
let mimeType = ContentAreaUtils.getMIMETypeForURI(uri) || "";
let msg = {
type: "Intent:Open",
mime: mimeType,
action: "android.intent.action.VIEW",
url: uri.spec,
packageName: appData.packageName,
className: appData.activityName
};
sendMessageToJava(msg);
},
openUriInApp: function openUriInApp(uri) {
let mimeType = ContentAreaUtils.getMIMETypeForURI(uri) || "";
let msg = {

View File

@ -2663,6 +2663,7 @@ Tab.prototype = {
this.browser.sessionHistory.addSHistoryListener(this);
this.browser.addEventListener("DOMContentLoaded", this, true);
this.browser.addEventListener("DOMFormHasPassword", this, true);
this.browser.addEventListener("DOMLinkAdded", this, true);
this.browser.addEventListener("DOMTitleChanged", this, true);
this.browser.addEventListener("DOMWindowClose", this, true);
@ -2811,6 +2812,7 @@ Tab.prototype = {
this.browser.sessionHistory.removeSHistoryListener(this);
this.browser.removeEventListener("DOMContentLoaded", this, true);
this.browser.removeEventListener("DOMFormHasPassword", this, true);
this.browser.removeEventListener("DOMLinkAdded", this, true);
this.browser.removeEventListener("DOMTitleChanged", this, true);
this.browser.removeEventListener("DOMWindowClose", this, true);
@ -3368,6 +3370,11 @@ Tab.prototype = {
break;
}
case "DOMFormHasPassword": {
LoginManagerContent.onFormPassword(aEvent);
break;
}
case "DOMLinkAdded": {
let target = aEvent.originalTarget;
if (!target.href || target.disabled)
@ -3540,6 +3547,9 @@ Tab.prototype = {
this._linkifier.linkifyNumbers(this.browser.contentWindow.document);
}
// Show page actions for helper apps.
HelperApps.updatePageAction(this.browser.currentURI);
if (!Reader.isEnabledForParseOnLoad)
return;

View File

@ -288,3 +288,6 @@ getUserMedia.sharingCameraAndMicrophone.message2 = Camera and microphone are on
#Reader mode
readerMode.enter = Enter Reader Mode
readerMode.exit = Exit Reader Mode
#Open in App
openInApp.pageAction = Open in App

View File

@ -3909,6 +3909,7 @@ pref("signon.SignonFileName3", "signons3.txt"); // obsolete
pref("signon.autofillForms", true);
pref("signon.autologin.proxy", false);
pref("signon.debug", false);
pref("signon.useDOMFormHasPassword", true);
// Satchel (Form Manager) prefs
pref("browser.formfill.debug", false);

View File

@ -184,7 +184,7 @@ interface nsIBrowserSearchInitObserver : nsISupports
void onInitComplete(in nsresult aStatus);
};
[scriptable, uuid(89beea9f-61a8-45d3-818d-b259f00195fe)]
[scriptable, uuid(939d74a4-5b01-463c-80c7-4301f0c0f9ef)]
interface nsIBrowserSearchService : nsISupports
{
/**

View File

@ -13,7 +13,8 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
var gEnabled = false, gDebug = false; // these mirror signon.* prefs
var gEnabled = false, gDebug = false, gAutofillForms = true; // these mirror signon.* prefs
var gUseDOMFormHasPassword = false; // use DOMFormHasPassword event for autofill
function log(...pieces) {
function generateLogMessage(args) {
@ -70,6 +71,8 @@ var observer = {
onPrefChange : function() {
gDebug = Services.prefs.getBoolPref("signon.debug");
gEnabled = Services.prefs.getBoolPref("signon.rememberSignons");
gAutofillForms = Services.prefs.getBoolPref("signon.autofillForms");
gUseDOMFormHasPassword = Services.prefs.getBoolPref("signon.useDOMFormHasPassword");
},
};
@ -92,6 +95,10 @@ var LoginManagerContent = {
},
onContentLoaded : function (event) {
// If we're using the new DOMFormHasPassword event, don't fill at pageload.
if (gUseDOMFormHasPassword)
return;
if (!event.isTrusted)
return;
@ -108,6 +115,64 @@ var LoginManagerContent = {
},
onFormPassword: function (event) {
// If we're not using the new DOMFormHasPassword event, only fill at pageload.
if (!gUseDOMFormHasPassword)
return;
if (!event.isTrusted)
return;
if (!gEnabled)
return;
let form = event.target;
let doc = form.ownerDocument;
log("onFormPassword for", doc.documentURI);
// If there are no logins for this site, bail out now.
let formOrigin = LoginUtils._getPasswordOrigin(doc.documentURI);
if (!Services.logins.countLogins(formOrigin, "", null))
return;
// If we're currently displaying a master password prompt, defer
// processing this form until the user handles the prompt.
if (Services.logins.uiBusy) {
log("deferring onFormPassword for", doc.documentURI);
let self = this;
let observer = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
observe: function (subject, topic, data) {
log("Got deferred onFormPassword notification:", topic);
// Only run observer once.
Services.obs.removeObserver(this, "passwordmgr-crypto-login");
Services.obs.removeObserver(this, "passwordmgr-crypto-loginCanceled");
if (topic == "passwordmgr-crypto-loginCanceled")
return;
self.onFormPassword(event);
},
handleEvent : function (event) {
// Not expected to be called
}
};
// Trickyness follows: We want an observer, but don't want it to
// cause leaks. So add the observer with a weak reference, and use
// a dummy event listener (a strong reference) to keep it alive
// until the form is destroyed.
Services.obs.addObserver(observer, "passwordmgr-crypto-login", true);
Services.obs.addObserver(observer, "passwordmgr-crypto-loginCanceled", true);
form.addEventListener("mozCleverClosureHack", observer);
return;
}
let autofillForm = gAutofillForms && !PrivateBrowsingUtils.isWindowPrivate(doc.defaultView);
this._fillForm(form, autofillForm, false, false, null);
},
/*
* onUsernameInput
*
@ -537,8 +602,7 @@ var LoginManagerContent = {
log("fillDocument processing", forms.length, "forms on", doc.documentURI);
var autofillForm = !PrivateBrowsingUtils.isWindowPrivate(doc.defaultView) &&
Services.prefs.getBoolPref("signon.autofillForms");
var autofillForm = gAutofillForms && !PrivateBrowsingUtils.isWindowPrivate(doc.defaultView);
var previousActionOrigin = null;
var foundLogins = null;

View File

@ -27,6 +27,7 @@ MOCHITEST_FILES = \
test_basic_form_observer_autocomplete.html \
test_basic_form_observer_foundLogins.html \
test_basic_form_pwonly.html \
test_basic_form_pwevent.html \
test_bug_227640.html \
test_bug_242956.html \
test_bug_360493_1.html \

View File

@ -21,6 +21,36 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
// Assume that the pref starts out true, so set to false
SpecialPowers.setBoolPref("signon.autofillForms", false);
var TestObserver = {
receivedNotificationFoundForm : false,
receivedNotificationFoundLogins : false,
dataFoundForm : "",
dataFoundLogins : null,
QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
observe : function (subject, topic, data) {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var pwmgr = Cc["@mozilla.org/login-manager;1"].
getService(Ci.nsILoginManager);
if (topic == "passwordmgr-found-form") {
info("got passwordmgr-found-form");
this.receivedNotificationFoundForm = true;
this.dataFoundForm = data;
// Now fill the form
pwmgr.fillForm(subject);
} else if (topic == "passwordmgr-found-logins") {
info("got passwordmgr-found-logins");
this.receivedNotificationFoundLogins = true;
this.dataFoundLogins = subject.QueryInterface(Ci.nsIPropertyBag2);
}
}
};
// Add the observer
var os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
os.addObserver(TestObserver, "passwordmgr-found-form", false);
os.addObserver(TestObserver, "passwordmgr-found-logins", false);
</script>
<p id="display"></p>
@ -42,35 +72,6 @@ SpecialPowers.setBoolPref("signon.autofillForms", false);
<script class="testbody" type="text/javascript">
/** Test for Login Manager: simple form with autofillForms disabled and notifying observers **/
var TestObserver = {
receivedNotificationFoundForm : false,
receivedNotificationFoundLogins : false,
dataFoundForm : "",
dataFoundLogins : null,
QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
observe : function (subject, topic, data) {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var pwmgr = Cc["@mozilla.org/login-manager;1"].
getService(Ci.nsILoginManager);
if (topic == "passwordmgr-found-form") {
this.receivedNotificationFoundForm = true;
this.dataFoundForm = data;
// Now fill the form
pwmgr.fillForm(subject);
} else if (topic == "passwordmgr-found-logins") {
this.receivedNotificationFoundLogins = true;
this.dataFoundLogins = subject.QueryInterface(Ci.nsIPropertyBag2);
}
}
};
// Add the observer
var os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
os.addObserver(TestObserver, "passwordmgr-found-form", false);
os.addObserver(TestObserver, "passwordmgr-found-logins", false);
function startTest(){
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
// Test that found-form observer is notified & got correct data

View File

@ -0,0 +1,61 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=355063
-->
<head>
<meta charset="utf-8"/>
<title>Test for Bug 355063</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript" src="pwmgr_common.js"></script>
<script type="application/javascript">
/** Test for Bug 355063 **/
function startTest() {
info("startTest");
addForm();
}
function addForm() {
info("addForm");
var c = document.getElementById("content");
c.innerHTML = "<form id=form1>form1: <input id=u1><input type=password id=p1></form><br>";
}
function checkForm() {
info("checkForm");
var userField = document.getElementById("u1");
var passField = document.getElementById("p1");
is(userField.value, "testuser", "checking filled username");
is(passField.value, "testpass", "checking filled password");
SpecialPowers.removeChromeEventListener("DOMFormHasPassword", checkForm);
SimpleTest.finish();
}
if (SpecialPowers.getBoolPref("signon.useDOMFormHasPassword")) {
commonInit();
// Password Manager's own listener should always have been added first, so
// the test's listener should be called after the pwmgr's listener fills in
// a login.
//
SpecialPowers.addChromeEventListener("DOMFormHasPassword", checkForm);
window.addEventListener("load", startTest);
SimpleTest.waitForExplicitFinish();
} else {
ok(true, "Skipping test when useDOMFormHasPassword is disabled");
}
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=355063">Mozilla Bug 355063</a>
<p id="display"></p>
<div id="content">
forms go here!
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -52,7 +52,12 @@ function startTest() {
SimpleTest.finish();
}
window.onload = startTest;
if (SpecialPowers.getBoolPref("signon.useDOMFormHasPassword")) {
info("skipping test when signon.useDOMFormHasPassword is enabled");
SimpleTest.finish();
} else {
window.onload = startTest;
}
</script>
</pre>
</body>

View File

@ -52,7 +52,12 @@ function startTest() {
SimpleTest.finish();
}
window.onload = startTest;
if (SpecialPowers.getBoolPref("signon.useDOMFormHasPassword")) {
info("skipping test when signon.useDOMFormHasPassword is enabled");
SimpleTest.finish();
} else {
window.onload = startTest;
}
</script>
</pre>
</body>

View File

@ -52,7 +52,12 @@ function startTest() {
SimpleTest.finish();
}
window.onload = startTest;
if (SpecialPowers.getBoolPref("signon.useDOMFormHasPassword")) {
info("skipping test when signon.useDOMFormHasPassword is enabled");
SimpleTest.finish();
} else {
window.onload = startTest;
}
</script>
</pre>
</body>

View File

@ -146,17 +146,19 @@ const BackgroundPageThumbs = {
browser.setAttribute("remote", "true");
browser.setAttribute("privatebrowsing", "true");
// Size the browser. Setting the width and height attributes doesn't
// work -- the resulting thumbnails are blank and transparent -- but
// setting the style does.
let width = {};
let height = {};
// Size the browser. Make its aspect ratio the same as the canvases' that
// the thumbnails are drawn into; the canvases' aspect ratio is the same as
// the screen's, so use that. Aim for a size in the ballpark of 1024x768.
let [swidth, sheight] = [{}, {}];
Cc["@mozilla.org/gfx/screenmanager;1"].
getService(Ci.nsIScreenManager).
primaryScreen.
GetRectDisplayPix({}, {}, width, height);
browser.style.width = width.value + "px";
browser.style.height = height.value + "px";
GetRectDisplayPix({}, {}, swidth, sheight);
let bwidth = Math.min(1024, swidth.value);
// Setting the width and height attributes doesn't work -- the resulting
// thumbnails are blank and transparent -- but setting the style does.
browser.style.width = bwidth + "px";
browser.style.height = (bwidth * sheight.value / swidth.value) + "px";
this._parentWin.document.documentElement.appendChild(browser);

View File

@ -1993,8 +1993,9 @@ SourceClient.prototype = {
return;
}
let { contentType, source } = aResponse;
let longString = this._client.activeThread.threadLongString(
aResponse.source);
source);
longString.substring(0, longString.length, function (aResponse) {
if (aResponse.error) {
aCallback(aResponse);
@ -2002,7 +2003,8 @@ SourceClient.prototype = {
}
aCallback({
source: aResponse.substring
source: aResponse.substring,
contentType: contentType
});
});
}.bind(this));

View File

@ -692,8 +692,7 @@ ThreadActor.prototype = {
}
packet.why = aReason;
let { url, line, column } = packet.frame.where;
this.sources.getOriginalLocation(url, line, column).then(aOrigPosition => {
this.sources.getOriginalLocation(packet.frame.where).then(aOrigPosition => {
packet.frame.where = aOrigPosition;
resolve(onPacket(packet))
.then(null, error => {
@ -704,7 +703,7 @@ ThreadActor.prototype = {
};
})
.then(packet => {
this.conn.send(packet)
this.conn.send(packet);
});
});
@ -772,10 +771,11 @@ ThreadActor.prototype = {
// Define the JS hook functions for stepping.
let onEnterFrame = aFrame => {
let { url } = this.synchronize(this.sources.getOriginalLocation(
aFrame.script.url,
aFrame.script.getOffsetLine(aFrame.offset),
getOffsetColumn(aFrame.offset, aFrame.script)));
let { url } = this.synchronize(this.sources.getOriginalLocation({
url: aFrame.script.url,
line: aFrame.script.getOffsetLine(aFrame.offset),
column: getOffsetColumn(aFrame.offset, aFrame.script)
}));
return this.sources.isBlackBoxed(url)
? undefined
@ -787,10 +787,11 @@ ThreadActor.prototype = {
let onPop = function TA_onPop(aCompletion) {
// onPop is called with 'this' set to the current frame.
let { url } = thread.synchronize(thread.sources.getOriginalLocation(
this.script.url,
this.script.getOffsetLine(this.offset),
getOffsetColumn(this.offset, this.script)));
let { url } = thread.synchronize(thread.sources.getOriginalLocation({
url: this.script.url,
line: this.script.getOffsetLine(this.offset),
column: getOffsetColumn(this.offset, this.script)
}));
if (thread.sources.isBlackBoxed(url)) {
return undefined;
@ -818,10 +819,11 @@ ThreadActor.prototype = {
let onStep = function TA_onStep() {
// onStep is called with 'this' set to the current frame.
let { url } = thread.synchronize(thread.sources.getOriginalLocation(
this.script.url,
this.script.getOffsetLine(this.offset),
getOffsetColumn(this.offset, this.script)));
let { url } = thread.synchronize(thread.sources.getOriginalLocation({
url: this.script.url,
line: this.script.getOffsetLine(this.offset),
column: getOffsetColumn(this.offset, this.script)
}));
if (thread.sources.isBlackBoxed(url)) {
return undefined;
@ -1029,7 +1031,7 @@ ThreadActor.prototype = {
if (this.state !== "paused") {
return { error: "wrongState",
message: "Debuggee must be paused to evaluate code." };
};
}
let frame = this._requestFrame(aRequest.frame);
if (!frame) {
@ -1040,7 +1042,7 @@ ThreadActor.prototype = {
if (!frame.environment) {
return { error: "notDebuggee",
message: "cannot access the environment of this frame." };
};
}
// We'll clobber the youngest frame if the eval causes a pause, so
// save our frame now to be restored after eval returns.
@ -1091,8 +1093,7 @@ ThreadActor.prototype = {
form.depth = i;
frames.push(form);
let { url, line, column } = form.where;
let promise = this.sources.getOriginalLocation(url, line, column)
let promise = this.sources.getOriginalLocation(form.where)
.then((aOrigLocation) => {
form.where = aOrigLocation;
let source = this.sources.source(form.where.url);
@ -1142,9 +1143,7 @@ ThreadActor.prototype = {
line: originalLine,
column: originalColumn } = aRequest.location;
let locationPromise = this.sources.getGeneratedLocation(originalSource,
originalLine,
originalColumn);
let locationPromise = this.sources.getGeneratedLocation(aRequest.location);
return locationPromise.then(({url, line, column}) => {
if (line == null ||
line < 0 ||
@ -1160,16 +1159,17 @@ ThreadActor.prototype = {
// If the original location of our generated location is different from
// the original location we attempted to set the breakpoint on, we will
// need to know so that we can set actualLocation on the response.
let originalLocation = this.sources.getOriginalLocation(url, line, column);
let originalLocation = this.sources.getOriginalLocation({
url: url,
line: line,
column: column
});
return all([response, originalLocation])
.then(([aResponse, {url, line}]) => {
if (aResponse.actualLocation) {
let actualOrigLocation = this.sources.getOriginalLocation(
aResponse.actualLocation.url,
aResponse.actualLocation.line,
aResponse.actualLocation.column);
return actualOrigLocation.then(function ({ url, line, column }) {
let actualOrigLocation = this.sources.getOriginalLocation(aResponse.actualLocation);
return actualOrigLocation.then(({ url, line, column }) => {
if (url !== originalSource
|| line !== originalLine
|| column !== originalColumn) {
@ -1505,7 +1505,7 @@ ThreadActor.prototype = {
return {
error: "notImplemented",
message: "eventListeners request is only supported in content debugging"
}
};
}
let els = Cc["@mozilla.org/eventlistenerservice;1"]
@ -1940,10 +1940,11 @@ ThreadActor.prototype = {
onDebuggerStatement: function TA_onDebuggerStatement(aFrame) {
// Don't pause if we are currently stepping (in or over) or the frame is
// black-boxed.
let { url } = this.synchronize(this.sources.getOriginalLocation(
aFrame.script.url,
aFrame.script.getOffsetLine(aFrame.offset),
getOffsetColumn(aFrame.offset, aFrame.script)));
let { url } = this.synchronize(this.sources.getOriginalLocation({
url: aFrame.script.url,
line: aFrame.script.getOffsetLine(aFrame.offset),
column: getOffsetColumn(aFrame.offset, aFrame.script)
}));
return this.sources.isBlackBoxed(url) || aFrame.onStep
? undefined
@ -1960,10 +1961,11 @@ ThreadActor.prototype = {
* The exception that was thrown.
*/
onExceptionUnwind: function TA_onExceptionUnwind(aFrame, aValue) {
let { url } = this.synchronize(this.sources.getOriginalLocation(
aFrame.script.url,
aFrame.script.getOffsetLine(aFrame.offset),
getOffsetColumn(aFrame.offset, aFrame.script)));
let { url } = this.synchronize(this.sources.getOriginalLocation({
url: aFrame.script.url,
line: aFrame.script.getOffsetLine(aFrame.offset),
column: getOffsetColumn(aFrame.offset, aFrame.script)
}));
if (this.sources.isBlackBoxed(url)) {
return undefined;
@ -2248,21 +2250,21 @@ SourceActor.prototype = {
// source because we can't guarantee that the cache has the most up to date
// content for this source like we can if it isn't source mapped.
return fetch(this._url, { loadFromCache: !this._sourceMap })
.then((aSource) => {
return this.threadActor.createValueGrip(
aSource, this.threadActor.threadLifetimePool);
})
.then((aSourceGrip) => {
.then(({ content, contentType }) => {
return {
from: this.actorID,
source: aSourceGrip
source: this.threadActor.createValueGrip(
content, this.threadActor.threadLifetimePool),
contentType: contentType
};
}, (aError) => {
})
.then(null, (aError) => {
reportError(aError, "Got an exception during SA_onSource: ");
return {
"from": this.actorID,
"error": "loadSourceError",
"message": "Could not load the source for " + this._url + "."
"message": "Could not load the source for " + this._url + ".\n"
+ safeErrorString(aError)
};
});
},
@ -3010,10 +3012,11 @@ BreakpointActor.prototype = {
// Don't pause if we are currently stepping (in or over) or the frame is
// black-boxed.
let { url } = this.threadActor.synchronize(
this.threadActor.sources.getOriginalLocation(
this.location.url,
this.location.line,
this.location.column));
this.threadActor.sources.getOriginalLocation({
url: this.location.url,
line: this.location.line,
column: this.location.column
}));
if (this.threadActor.sources.isBlackBoxed(url) || aFrame.onStep) {
return undefined;
@ -3483,8 +3486,8 @@ ThreadSources.prototype = {
return this._sourceMaps[aAbsSourceMapURL];
}
let promise = fetch(aAbsSourceMapURL).then(rawSourceMap => {
let map = new SourceMapConsumer(rawSourceMap);
let promise = fetch(aAbsSourceMapURL).then(({ content }) => {
let map = new SourceMapConsumer(content);
this._setSourceMapRoot(map, aAbsSourceMapURL, aScriptURL);
return map;
});
@ -3515,28 +3518,27 @@ ThreadSources.prototype = {
* Returns a promise of the location in the original source if the source is
* source mapped, otherwise a promise of the same location.
*/
getOriginalLocation:
function TS_getOriginalLocation(aSourceUrl, aLine, aColumn) {
if (aSourceUrl in this._sourceMapsByGeneratedSource) {
return this._sourceMapsByGeneratedSource[aSourceUrl]
.then(function (aSourceMap) {
let { source, line, column } = aSourceMap.originalPositionFor({
line: aLine,
column: aColumn
});
return {
url: source,
getOriginalLocation: function TS_getOriginalLocation({ url, line, column }) {
if (url in this._sourceMapsByGeneratedSource) {
return this._sourceMapsByGeneratedSource[url]
.then((aSourceMap) => {
let { source: aSourceURL, line: aLine, column: aColumn } = aSourceMap.originalPositionFor({
line: line,
column: column
});
return {
url: aSourceURL,
line: aLine,
column: aColumn
};
});
}
// No source map
return resolve({
url: aSourceUrl,
line: aLine,
column: aColumn
url: url,
line: line,
column: column
});
},
@ -3549,29 +3551,28 @@ ThreadSources.prototype = {
* the tables this function uses; thus, it won't know that S's original
* source URLs map to S until P is resolved.
*/
getGeneratedLocation:
function TS_getGeneratedLocation(aSourceUrl, aLine, aColumn) {
if (aSourceUrl in this._sourceMapsByOriginalSource) {
return this._sourceMapsByOriginalSource[aSourceUrl]
getGeneratedLocation: function TS_getGeneratedLocation({ url, line, column }) {
if (url in this._sourceMapsByOriginalSource) {
return this._sourceMapsByOriginalSource[url]
.then((aSourceMap) => {
let { line, column } = aSourceMap.generatedPositionFor({
source: aSourceUrl,
line: aLine,
column: aColumn == null ? Infinity : aColumn
let { line: aLine, column: aColumn } = aSourceMap.generatedPositionFor({
source: url,
line: line,
column: column == null ? Infinity : column
});
return {
url: this._generatedUrlsByOriginalUrl[aSourceUrl],
line: line,
column: column
url: this._generatedUrlsByOriginalUrl[url],
line: aLine,
column: aColumn
};
});
}
// No source map
return resolve({
url: aSourceUrl,
line: aLine,
column: aColumn
url: url,
line: line,
column: column
});
},
@ -3698,6 +3699,7 @@ function fetch(aURL, aOptions={ loadFromCache: true }) {
let scheme;
let url = aURL.split(" -> ").pop();
let charset;
let contentType;
try {
scheme = Services.io.extractScheme(url);
@ -3714,13 +3716,14 @@ function fetch(aURL, aOptions={ loadFromCache: true }) {
case "chrome":
case "resource":
try {
NetUtil.asyncFetch(url, function onFetch(aStream, aStatus) {
NetUtil.asyncFetch(url, function onFetch(aStream, aStatus, aRequest) {
if (!Components.isSuccessCode(aStatus)) {
deferred.reject(new Error("Request failed: " + url));
return;
}
let source = NetUtil.readInputStreamToString(aStream, aStream.available());
contentType = aRequest.contentType;
deferred.resolve(source);
aStream.close();
});
@ -3756,6 +3759,7 @@ function fetch(aURL, aOptions={ loadFromCache: true }) {
}
charset = channel.contentCharset;
contentType = channel.contentType;
deferred.resolve(chunks.join(""));
}
};
@ -3767,8 +3771,11 @@ function fetch(aURL, aOptions={ loadFromCache: true }) {
break;
}
return deferred.promise.then(function (source) {
return convertToUnicode(source, charset);
return deferred.promise.then(source => {
return {
content: convertToUnicode(source, charset),
contentType: contentType
};
});
}

View File

@ -22,17 +22,12 @@ function run_test()
gClient.connect(function() {
attachTestTabAndResume(gClient, "test-grips", function(aResponse, aTabClient, aThreadClient) {
gThreadClient = aThreadClient;
gThreadClient.addListener("unsolicitedPause", unsolicitedPauseListener);
test_source();
});
});
do_test_pending();
}
function unsolicitedPauseListener(aEvent, aPacket, aContinue) {
gContinue = aContinue;
}
function test_source()
{
DebuggerServer.LONG_STRING_LENGTH = 200;
@ -43,7 +38,6 @@ function test_source()
do_check_true(!!aResponse.sources);
gClient.compat.supportsFeature("sources").then(function (supported) {
do_check_true(supported);
});
let source = aResponse.sources.filter(function (s) {
@ -57,6 +51,7 @@ function test_source()
do_check_true(!!aResponse);
do_check_true(!aResponse.error);
do_check_true(!!aResponse.source);
do_check_true(aResponse.contentType.contains("javascript"));
do_check_eq(readFile("test_source-01.js"),
aResponse.source);

View File

@ -2543,6 +2543,24 @@ UpdateService.prototype = {
* The timer that fired
*/
notify: function AUS_notify(timer) {
// The telemetry below is specific to background notification.
this._sendBoolPrefTelemetryPing(PREF_APP_UPDATE_ENABLED,
"UPDATER_UPDATES_ENABLED");
this._sendBoolPrefTelemetryPing(PREF_APP_UPDATE_METRO_ENABLED,
"UPDATER_UPDATES_METRO_ENABLED");
this._sendBoolPrefTelemetryPing(PREF_APP_UPDATE_AUTO,
"UPDATER_UPDATES_AUTOMATIC");
this._sendBoolPrefTelemetryPing(PREF_APP_UPDATE_STAGING_ENABLED,
"UPDATER_STAGE_ENABLED");
#ifdef XP_WIN
this._sendBoolPrefTelemetryPing(PREF_APP_UPDATE_SERVICE_ENABLED,
"UPDATER_SERVICE_ENABLED");
this._sendIntPrefTelemetryPing(PREF_APP_UPDATE_SERVICE_ERRORS,
"UPDATER_SERVICE_ERRORS");
this._sendServiceInstalledTelemetryPing();
#endif
this._checkForBackgroundUpdates(true);
},
@ -2561,24 +2579,10 @@ UpdateService.prototype = {
*/
_checkForBackgroundUpdates: function AUS__checkForBackgroundUpdates(isNotify) {
this._isNotify = isNotify;
// This ensures that telemetry is gathered even if update is disabled.
// From this point on, the telemetry reported differentiates between a call
// to notify and a call to checkForBackgroundUpdates so they are reported
// separately.
this._sendLastNotifyIntervalPing();
this._sendBoolPrefTelemetryPing(PREF_APP_UPDATE_ENABLED,
"UPDATER_UPDATES_ENABLED");
this._sendBoolPrefTelemetryPing(PREF_APP_UPDATE_METRO_ENABLED,
"UPDATER_UPDATES_METRO_ENABLED");
this._sendBoolPrefTelemetryPing(PREF_APP_UPDATE_AUTO,
"UPDATER_UPDATES_AUTOMATIC");
this._sendBoolPrefTelemetryPing(PREF_APP_UPDATE_STAGING_ENABLED,
"UPDATER_STAGE_ENABLED");
#ifdef XP_WIN
this._sendBoolPrefTelemetryPing(PREF_APP_UPDATE_SERVICE_ENABLED,
"UPDATER_SERVICE_ENABLED");
this._sendIntPrefTelemetryPing(PREF_APP_UPDATE_SERVICE_ERRORS,
"UPDATER_SERVICE_ERRORS");
this._sendServiceInstalledTelemetryPing();
#endif
// If a download is in progress or the patch has been staged do nothing.
if (this.isDownloading) {

View File

@ -109,7 +109,7 @@ var gSwitchApp = false;
var gDisableReplaceFallback = false;
// Time to wait for the test helper process before continuing the test
const TEST_HELPER_TIMEOUT = 2000;
const TEST_HELPER_TIMEOUT = 100;
// Use a copy of the main application executable for the test to avoid main
// executable in use errors.
@ -1057,7 +1057,7 @@ function waitForHelperSleep() {
return;
}
output.remove(false);
do_timeout(TEST_HELPER_TIMEOUT, doUpdate);
doUpdate();
}
function waitForHelperFinished() {
@ -1070,7 +1070,7 @@ function waitForHelperFinished() {
}
// Give the lock file process time to unlock the file before deleting the
// input and output files.
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperFinishFileUnlock);
waitForHelperFinishFileUnlock();
}
function waitForHelperFinishFileUnlock() {
@ -1090,13 +1090,13 @@ function waitForHelperFinishFileUnlock() {
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperFinishFileUnlock);
return;
}
do_timeout(TEST_HELPER_TIMEOUT, checkUpdate);
checkUpdate();
}
function setupHelperFinish() {
let input = getApplyDirFile("a/b/input", true);
writeFile(input, "finish\n");
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperFinished);
waitForHelperFinished();
}
/**
@ -1570,7 +1570,7 @@ function removeCallbackCopy() {
}
// Use a timeout to give any files that were in use additional
// time to close. Same as updater.exe without service tests.
do_timeout(TEST_HELPER_TIMEOUT, do_test_finished);
do_test_finished();
}
// Waits until files that are in use that break tests are no longer in use and