summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@gmail.com>2018-04-28 17:57:18 +0200
committerwolfbeast <mcwerewolf@gmail.com>2018-04-28 17:57:18 +0200
commitf69729b0aa1d8cd1964994919ab30ce7c7d9f410 (patch)
treed877e04983b628a9e45271615fc9486712e4a404
parentb53db93006f732fb2e140137e4713dedca1700d9 (diff)
parentde057c7a5635e65f45ce47162d226b1ddf24e8aa (diff)
downloadUXP-f69729b0aa1d8cd1964994919ab30ce7c7d9f410.tar
UXP-f69729b0aa1d8cd1964994919ab30ce7c7d9f410.tar.gz
UXP-f69729b0aa1d8cd1964994919ab30ce7c7d9f410.tar.lz
UXP-f69729b0aa1d8cd1964994919ab30ce7c7d9f410.tar.xz
UXP-f69729b0aa1d8cd1964994919ab30ce7c7d9f410.zip
Merge branch 'master' of https://github.com/MoonchildProductions/UXP
-rw-r--r--application/palemoon/base/content/browser.js327
-rw-r--r--application/palemoon/base/content/newtab/grid.js7
-rw-r--r--application/palemoon/base/content/openLocation.js77
-rw-r--r--application/palemoon/base/content/tabbrowser.xml149
-rw-r--r--application/palemoon/base/content/urlbarBindings.xml140
-rw-r--r--application/palemoon/components/downloads/content/allDownloadsViewOverlay.js59
-rw-r--r--application/palemoon/components/downloads/content/downloads.js3
-rw-r--r--application/palemoon/components/downloads/content/indicator.js21
-rw-r--r--application/palemoon/components/sessionstore/SessionStore.jsm8
-rw-r--r--application/palemoon/locales/en-US/chrome/browser/browser.properties1
-rw-r--r--devtools/client/shared/widgets/TableWidget.js9
-rw-r--r--devtools/client/storage/ui.js42
12 files changed, 510 insertions, 333 deletions
diff --git a/application/palemoon/base/content/browser.js b/application/palemoon/base/content/browser.js
index 556e7a2b7..6dbd9677e 100644
--- a/application/palemoon/base/content/browser.js
+++ b/application/palemoon/base/content/browser.js
@@ -10,6 +10,9 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource:///modules/RecentWindow.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Task",
+ "resource://gre/modules/Task.jsm");
+
XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
"resource:///modules/CharsetMenu.jsm");
@@ -1895,88 +1898,126 @@ function loadURI(uri, referrer, postData, allowThirdPartyFixup) {
} catch (e) {}
}
-function getShortcutOrURI(aURL, aPostDataRef, aMayInheritPrincipal) {
- // Initialize outparam to false
- if (aMayInheritPrincipal)
- aMayInheritPrincipal.value = false;
+/**
+ * Given a urlbar value, discerns between URIs, keywords and aliases.
+ *
+ * @param url
+ * The urlbar value.
+ * @param callback (optional, deprecated)
+ * The callback function invoked when done. This parameter is
+ * deprecated, please use the Promise that is returned.
+ *
+ * @return Promise<{ postData, url, mayInheritPrincipal }>
+ */
+function getShortcutOrURIAndPostData(url, callback = null) {
+ if (callback) {
+ Deprecated.warning("Please use the Promise returned by " +
+ "getShortcutOrURIAndPostData() instead of passing a " +
+ "callback",
+ "https://bugzilla.mozilla.org/show_bug.cgi?id=1100294");
+ }
- var shortcutURL = null;
- var keyword = aURL;
- var param = "";
+ return Task.spawn(function* () {
+ let mayInheritPrincipal = false;
+ let postData = null;
+ let shortcutURL = null;
+ let keyword = url;
+ let param = "";
- var offset = aURL.indexOf(" ");
- if (offset > 0) {
- keyword = aURL.substr(0, offset);
- param = aURL.substr(offset + 1);
- }
+ let offset = url.indexOf(" ");
+ if (offset > 0) {
+ keyword = url.substr(0, offset);
+ param = url.substr(offset + 1);
+ }
- if (!aPostDataRef)
- aPostDataRef = {};
+ let engine = Services.search.getEngineByAlias(keyword);
+ if (engine) {
+ let submission = engine.getSubmission(param, null, "keyword");
+ postData = submission.postData;
+ return { postData: submission.postData, url: submission.uri.spec,
+ mayInheritPrincipal };
+ }
- var engine = Services.search.getEngineByAlias(keyword);
- if (engine) {
- var submission = engine.getSubmission(param);
- aPostDataRef.value = submission.postData;
- return submission.uri.spec;
- }
+ let entry = yield PlacesUtils.keywords.fetch(keyword);
+ if (entry) {
+ shortcutURL = entry.url.href;
+ postData = entry.postData;
+ }
- [shortcutURL, aPostDataRef.value] =
- PlacesUtils.getURLAndPostDataForKeyword(keyword);
+ if (!shortcutURL) {
+ return { postData, url, mayInheritPrincipal };
+ }
- if (!shortcutURL)
- return aURL;
+ let escapedPostData = "";
+ if (postData)
+ escapedPostData = unescape(postData);
- var postData = "";
- if (aPostDataRef.value)
- postData = unescape(aPostDataRef.value);
+ if (/%s/i.test(shortcutURL) || /%s/i.test(escapedPostData)) {
+ let charset = "";
+ const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/;
+ let matches = shortcutURL.match(re);
- if (/%s/i.test(shortcutURL) || /%s/i.test(postData)) {
- var charset = "";
- const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/;
- var matches = shortcutURL.match(re);
- if (matches)
- [, shortcutURL, charset] = matches;
- else {
- // Try to get the saved character-set.
- try {
- // makeURI throws if URI is invalid.
- // Will return an empty string if character-set is not found.
- charset = PlacesUtils.history.getCharsetForURI(makeURI(shortcutURL));
- } catch (e) {}
- }
+ if (matches) {
+ [, shortcutURL, charset] = matches;
+ } else {
+ let uri;
+ try {
+ // makeURI() throws if URI is invalid.
+ uri = makeURI(shortcutURL);
+ } catch (ex) {}
+
+ if (uri) {
+ // Try to get the saved character-set.
+ // Will return an empty string if character-set is not found.
+ charset = yield PlacesUtils.getCharsetForURI(uri);
+ }
+ }
- // encodeURIComponent produces UTF-8, and cannot be used for other charsets.
- // escape() works in those cases, but it doesn't uri-encode +, @, and /.
- // Therefore we need to manually replace these ASCII characters by their
- // encodeURIComponent result, to match the behavior of nsEscape() with
- // url_XPAlphas
- var encodedParam = "";
- if (charset && charset != "UTF-8")
- encodedParam = escape(convertFromUnicode(charset, param)).
- replace(/[+@\/]+/g, encodeURIComponent);
- else // Default charset is UTF-8
- encodedParam = encodeURIComponent(param);
+ // encodeURIComponent produces UTF-8, and cannot be used for other charsets.
+ // escape() works in those cases, but it doesn't uri-encode +, @, and /.
+ // Therefore we need to manually replace these ASCII characters by their
+ // encodeURIComponent result, to match the behavior of nsEscape() with
+ // url_XPAlphas
+ let encodedParam = "";
+ if (charset && charset != "UTF-8")
+ encodedParam = escape(convertFromUnicode(charset, param)).
+ replace(/[+@\/]+/g, encodeURIComponent);
+ else // Default charset is UTF-8
+ encodedParam = encodeURIComponent(param);
- shortcutURL = shortcutURL.replace(/%s/g, encodedParam).replace(/%S/g, param);
+ shortcutURL = shortcutURL.replace(/%s/g, encodedParam).replace(/%S/g, param);
- if (/%s/i.test(postData)) // POST keyword
- aPostDataRef.value = getPostDataStream(postData, param, encodedParam,
- "application/x-www-form-urlencoded");
- }
- else if (param) {
- // This keyword doesn't take a parameter, but one was provided. Just return
- // the original URL.
- aPostDataRef.value = null;
+ if (/%s/i.test(escapedPostData)) // POST keyword
+ postData = getPostDataStream(escapedPostData, param, encodedParam,
+ "application/x-www-form-urlencoded");
- return aURL;
- }
+ // This URL came from a bookmark, so it's safe to let it inherit the current
+ // document's principal.
+ mayInheritPrincipal = true;
+
+ return { postData, url: shortcutURL, mayInheritPrincipal };
+ }
+
+ if (param) {
+ // This keyword doesn't take a parameter, but one was provided. Just return
+ // the original URL.
+ postData = null;
+
+ return { postData, url, mayInheritPrincipal };
+ }
- // This URL came from a bookmark, so it's safe to let it inherit the current
- // document's principal.
- if (aMayInheritPrincipal)
- aMayInheritPrincipal.value = true;
+ // This URL came from a bookmark, so it's safe to let it inherit the current
+ // document's principal.
+ mayInheritPrincipal = true;
- return shortcutURL;
+ return { postData, url: shortcutURL, mayInheritPrincipal };
+ }).then(data => {
+ if (callback) {
+ callback(data);
+ }
+
+ return data;
+ });
}
function getPostDataStream(aStringData, aKeyword, aEncKeyword, aType) {
@@ -2635,8 +2676,8 @@ var browserDragAndDrop = {
}
},
- drop: function (aEvent, aName, aDisallowInherit) {
- return Services.droppedLinkHandler.dropLink(aEvent, aName, aDisallowInherit);
+ dropLinks: function (aEvent, aDisallowInherit) {
+ return Services.droppedLinkHandler.dropLinks(aEvent, aDisallowInherit);
}
};
@@ -2644,8 +2685,10 @@ var homeButtonObserver = {
onDrop: function (aEvent)
{
// disallow setting home pages that inherit the principal
- let url = browserDragAndDrop.drop(aEvent, {}, true);
- setTimeout(openHomeDialog, 0, url);
+ let links = browserDragAndDrop.dropLinks(aEvent, true);
+ if (links.length) {
+ setTimeout(openHomeDialog, 0, links.map(link => link.url).join("|"));
+ }
},
onDragOver: function (aEvent)
@@ -2661,18 +2704,24 @@ var homeButtonObserver = {
function openHomeDialog(aURL)
{
var promptTitle = gNavigatorBundle.getString("droponhometitle");
- var promptMsg = gNavigatorBundle.getString("droponhomemsg");
+ var promptMsg;
+ if (aURL.includes("|")) {
+ promptMsg = gNavigatorBundle.getString("droponhomemsgMultiple");
+ } else {
+ promptMsg = gNavigatorBundle.getString("droponhomemsg");
+ }
+
var pressedVal = Services.prompt.confirmEx(window, promptTitle, promptMsg,
Services.prompt.STD_YES_NO_BUTTONS,
null, null, null, null, {value:0});
if (pressedVal == 0) {
try {
- var str = Components.classes["@mozilla.org/supports-string;1"]
- .createInstance(Components.interfaces.nsISupportsString);
- str.data = aURL;
+ var homepageStr = Components.classes["@mozilla.org/supports-string;1"]
+ .createInstance(Components.interfaces.nsISupportsString);
+ homepageStr.data = aURL;
gPrefService.setComplexValue("browser.startup.homepage",
- Components.interfaces.nsISupportsString, str);
+ Components.interfaces.nsISupportsString, homepageStr);
} catch (ex) {
dump("Failed to set the home page.\n"+ex+"\n");
}
@@ -2720,13 +2769,16 @@ var newTabButtonObserver = {
onDrop: function (aEvent)
{
- let url = browserDragAndDrop.drop(aEvent, { });
- var postData = {};
- url = getShortcutOrURI(url, postData);
- if (url) {
- // allow third-party services to fixup this URL
- openNewTabWith(url, null, postData.value, aEvent, true);
- }
+ let links = browserDragAndDrop.dropLinks(aEvent);
+ Task.spawn(function*() {
+ for (let link of links) {
+ let data = yield getShortcutOrURIAndPostData(link.url);
+ if (data.url) {
+ // allow third-party services to fixup this URL
+ openNewTabWith(data.url, null, data.postData, aEvent, true);
+ }
+ }
+ });
}
}
@@ -2740,13 +2792,16 @@ var newWindowButtonObserver = {
},
onDrop: function (aEvent)
{
- let url = browserDragAndDrop.drop(aEvent, { });
- var postData = {};
- url = getShortcutOrURI(url, postData);
- if (url) {
- // allow third-party services to fixup this URL
- openNewWindowWith(url, null, postData.value, true);
- }
+ let links = browserDragAndDrop.dropLinks(aEvent);
+ Task.spawn(function*() {
+ for (let link of links) {
+ let data = yield getShortcutOrURIAndPostData(link.url);
+ if (data.url) {
+ // allow third-party services to fixup this URL
+ openNewWindowWith(data.url, null, data.postData, true);
+ }
+ }
+ });
}
}
@@ -5034,36 +5089,81 @@ function middleMousePaste(event) {
// bar's behavior (stripsurroundingwhitespace)
clipboard = clipboard.replace(/\s*\n\s*/g, "");
- let mayInheritPrincipal = { value: false };
- let url = getShortcutOrURI(clipboard, mayInheritPrincipal);
- try {
- makeURI(url);
- } catch (ex) {
- // Not a valid URI.
- return;
+ // if it's not the current tab, we don't need to do anything because the
+ // browser doesn't exist.
+ let where = whereToOpenLink(event, true, false);
+ let lastLocationChange;
+ if (where == "current") {
+ lastLocationChange = gBrowser.selectedBrowser.lastLocationChange;
}
- try {
- addToUrlbarHistory(url);
- } catch (ex) {
- // Things may go wrong when adding url to session history,
- // but don't let that interfere with the loading of the url.
- Cu.reportError(ex);
- }
+ getShortcutOrURIAndPostData(clipboard).then(data => {
+ try {
+ makeURI(data.url);
+ } catch (ex) {
+ // Not a valid URI.
+ return;
+ }
- openUILink(url, event,
- { ignoreButton: true,
- disallowInheritPrincipal: !mayInheritPrincipal.value });
+ try {
+ addToUrlbarHistory(data.url);
+ } catch (ex) {
+ // Things may go wrong when adding url to session history,
+ // but don't let that interfere with the loading of the url.
+ Cu.reportError(ex);
+ }
+
+ if (where != "current" ||
+ lastLocationChange == gBrowser.selectedBrowser.lastLocationChange) {
+ openUILink(data.url, event,
+ { ignoreButton: true,
+ disallowInheritPrincipal: !data.mayInheritPrincipal,
+ initiatingDoc: event ? event.target.ownerDocument : null });
+ }
+ });
event.stopPropagation();
}
-function handleDroppedLink(event, url, name)
+// handleDroppedLink has the following 2 overloads:
+// handleDroppedLink(event, url, name)
+// handleDroppedLink(event, links)
+function handleDroppedLink(event, urlOrLinks, name)
{
- let postData = { };
- let uri = getShortcutOrURI(url, postData);
- if (uri)
- loadURI(uri, null, postData.value, false);
+ let links;
+ if (Array.isArray(urlOrLinks)) {
+ links = urlOrLinks;
+ } else {
+ links = [{ url: urlOrLinks, name, type: "" }];
+ }
+
+ let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange;
+
+ let userContextId = gBrowser.selectedBrowser
+ .getAttribute("usercontextid") || 0;
+
+ let inBackground = Services.prefs.getBoolPref("browser.tabs.loadInBackground");
+ if (event.shiftKey)
+ inBackground = !inBackground;
+
+ Task.spawn(function*() {
+ let urls = [];
+ let postDatas = [];
+ for (let link of links) {
+ let data = yield getShortcutOrURIAndPostData(link.url);
+ urls.push(data.url);
+ postDatas.push(data.postData);
+ }
+ if (lastLocationChange == gBrowser.selectedBrowser.lastLocationChange) {
+ gBrowser.loadTabs(urls, {
+ inBackground,
+ replace: true,
+ allowThirdPartyFixup: false,
+ postDatas,
+ userContextId,
+ });
+ }
+ });
// Keep the event from being handled by the dragDrop listeners
// built-in to goanna if they happen to be above us.
@@ -5178,7 +5278,6 @@ function charsetLoadListener() {
}
}
-
var gPageStyleMenu = {
_getAllStyleSheets: function (frameset) {
diff --git a/application/palemoon/base/content/newtab/grid.js b/application/palemoon/base/content/newtab/grid.js
index 46e0b804b..a614d0396 100644
--- a/application/palemoon/base/content/newtab/grid.js
+++ b/application/palemoon/base/content/newtab/grid.js
@@ -59,8 +59,13 @@ var gGrid = {
* Refreshes the grid and re-creates all sites.
*/
refresh: function Grid_refresh() {
+ let cells = this.cells;
+ if (!cells) {
+ return;
+ }
+
// Remove all sites.
- this.cells.forEach(function (cell) {
+ cells.forEach(function (cell) {
let node = cell.node;
let child = node.firstElementChild;
diff --git a/application/palemoon/base/content/openLocation.js b/application/palemoon/base/content/openLocation.js
index 316dfac70..1a10334c7 100644
--- a/application/palemoon/base/content/openLocation.js
+++ b/application/palemoon/base/content/openLocation.js
@@ -61,45 +61,52 @@ function doEnabling()
function open()
{
- var url;
- var postData = {};
- var mayInheritPrincipal = {value: false};
- if (browser)
- url = browser.getShortcutOrURI(dialog.input.value, postData, mayInheritPrincipal);
- else
- url = dialog.input.value;
+ getShortcutOrURIAndPostData(dialog.input.value).then(data => {
+ let url;
+ let postData = null;
+ let mayInheritPrincipal = false;
+
+ if (browser) {
+ url = data.url;
+ postData = data.postData;
+ mayInheritPrincipal = data.mayInheritPrincipal;
+ } else {
+ url = dialog.input.value;
+ }
- try {
- // Whichever target we use for the load, we allow third-party services to
- // fixup the URI
- switch (dialog.openWhereList.value) {
- case "0":
- var webNav = Components.interfaces.nsIWebNavigation;
- var flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
- webNav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
- if (!mayInheritPrincipal.value)
- flags |= webNav.LOAD_FLAGS_DISALLOW_INHERIT_OWNER;
- browser.gBrowser.loadURIWithFlags(url, flags, null, null, postData.value);
- break;
- case "1":
- window.opener.delayedOpenWindow(getBrowserURL(), "all,dialog=no",
- url, postData.value, null, null, true);
- break;
- case "3":
- browser.delayedOpenTab(url, null, null, postData.value, true);
- break;
+ try {
+ // Whichever target we use for the load, we allow third-party services to
+ // fixup the URI
+ switch (dialog.openWhereList.value) {
+ case "0":
+ var webNav = Components.interfaces.nsIWebNavigation;
+ var flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
+ webNav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
+ if (!mayInheritPrincipal)
+ flags |= webNav.LOAD_FLAGS_DISALLOW_INHERIT_OWNER;
+ browser.gBrowser.loadURIWithFlags(url, flags, null, null, postData);
+ break;
+ case "1":
+ window.opener.delayedOpenWindow(getBrowserURL(), "all,dialog=no",
+ url, postData, null, null, true);
+ break;
+ case "3":
+ browser.delayedOpenTab(url, null, null, postData, true);
+ break;
+ }
+ }
+ catch(exception) {
}
- }
- catch(exception) {
- }
- if (pref) {
- gOpenLocationLastURL.value = dialog.input.value;
- pref.setIntPref("general.open_location.last_window_choice", dialog.openWhereList.value);
- }
+ if (pref) {
+ gOpenLocationLastURL.value = dialog.input.value;
+ pref.setIntPref("general.open_location.last_window_choice", dialog.openWhereList.value);
+ }
+
+ // Delay closing slightly to avoid timing bug on Linux.
+ window.close();
+ });
- // Delay closing slightly to avoid timing bug on Linux.
- window.close();
return false;
}
diff --git a/application/palemoon/base/content/tabbrowser.xml b/application/palemoon/base/content/tabbrowser.xml
index a7cc6deea..c06b49af0 100644
--- a/application/palemoon/base/content/tabbrowser.xml
+++ b/application/palemoon/base/content/tabbrowser.xml
@@ -570,6 +570,12 @@
const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
const nsIChannel = Components.interfaces.nsIChannel;
+ let location, originalLocation;
+ try {
+ aRequest.QueryInterface(nsIChannel)
+ location = aRequest.URI;
+ originalLocation = aRequest.originalURI;
+ } catch (ex) {}
if (aStateFlags & nsIWebProgressListener.STATE_START) {
this.mRequestCount++;
@@ -588,16 +594,8 @@
if (aStateFlags & nsIWebProgressListener.STATE_START &&
aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
- // It's okay to clear what the user typed when we start
- // loading a document. If the user types, this counter gets
- // set to zero, if the document load ends without an
- // onLocationChange, this counter gets decremented
- // (so we keep it while switching tabs after failed loads)
- // We need to add 2 because loadURIWithFlags may have
- // cancelled a pending load which would have cleared
- // its anchor scroll detection temporary increment.
if (aWebProgress.isTopLevel)
- this.mBrowser.userTypedClear += 2;
+ this.mBrowser.urlbarChangeTracker.startedLoad();
if (this._shouldShowProgress(aRequest)) {
if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) {
@@ -625,8 +623,8 @@
this.mTab.removeAttribute("progress");
if (aWebProgress.isTopLevel) {
- if (!Components.isSuccessCode(aStatus) &&
- !isTabEmpty(this.mTab)) {
+ let isSuccessful = Components.isSuccessCode(aStatus);
+ if (!isSuccessful && !isTabEmpty(this.mTab)) {
// Restore the current document's location in case the
// request was stopped (possibly from a content script)
// before the location changed.
@@ -635,14 +633,8 @@
if (this.mTab.selected && gURLBar)
URLBarSetURI();
- } else {
- // The document is done loading, we no longer want the
- // value cleared.
-
- if (this.mBrowser.userTypedClear > 1)
- this.mBrowser.userTypedClear -= 2;
- else if (this.mBrowser.userTypedClear > 0)
- this.mBrowser.userTypedClear--;
+ } else if (isSuccessful) {
+ this.mBrowser.urlbarChangeTracker.finishedLoad();
}
if (!this.mBrowser.mIconURL)
@@ -652,8 +644,6 @@
if (this.mBlank)
this.mBlank = false;
- var location = aRequest.QueryInterface(nsIChannel).URI;
-
// For keyword URIs clear the user typed value since they will be changed into real URIs
if (location.scheme == "keyword")
this.mBrowser.userTypedValue = null;
@@ -696,13 +686,12 @@
let topLevel = aWebProgress.isTopLevel;
if (topLevel) {
- // If userTypedClear > 0, the document loaded correctly and we should be
- // clearing the user typed value. We also need to clear the typed value
+ // We need to clear the typed value
// if the document failed to load, to make sure the urlbar reflects the
// failed URI (particularly for SSL errors). However, don't clear the value
// if the error page's URI is about:blank, because that causes complete
// loss of urlbar contents for invalid URI errors (see bug 867957).
- if (this.mBrowser.userTypedClear > 0 ||
+ if (this.mBrowser.didStartLoadSinceLastUserTyping() ||
((aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) &&
aLocation.spec != "about:blank"))
this.mBrowser.userTypedValue = null;
@@ -738,8 +727,10 @@
aFlags]);
}
- if (topLevel)
+ if (topLevel) {
this.mBrowser.lastURI = aLocation;
+ this.mBrowser.lastLocationChange = Date.now();
+ }
},
onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) {
@@ -1312,6 +1303,24 @@
<parameter name="aLoadInBackground"/>
<parameter name="aReplace"/>
<body><![CDATA[
+ let aAllowThirdPartyFixup;
+ let aTargetTab;
+ let aNewIndex = -1;
+ let aPostDatas = [];
+ let aUserContextId;
+ if (arguments.length == 2 &&
+ typeof arguments[1] == "object") {
+ let params = arguments[1];
+ aLoadInBackground = params.inBackground;
+ aReplace = params.replace;
+ aAllowThirdPartyFixup = params.allowThirdPartyFixup;
+ aTargetTab = params.targetTab;
+ aNewIndex = typeof params.newIndex === "number" ?
+ params.newIndex : aNewIndex;
+ aPostDatas = params.postDatas || aPostDatas;
+ aUserContextId = params.userContextId;
+ }
+
if (!aURIs.length)
return;
@@ -1329,22 +1338,53 @@
var multiple = aURIs.length > 1;
var owner = multiple || aLoadInBackground ? null : this.selectedTab;
var firstTabAdded = null;
+ var targetTabIndex = -1;
if (aReplace) {
+ let browser;
+ if (aTargetTab) {
+ browser = this.getBrowserForTab(aTargetTab);
+ targetTabIndex = aTargetTab._tPos;
+ } else {
+ browser = this.mCurrentBrowser;
+ targetTabIndex = this.tabContainer.selectedIndex;
+ }
+ let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
+ if (aAllowThirdPartyFixup) {
+ flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
+ Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
+ }
try {
- this.loadURI(aURIs[0], null, null);
+ browser.loadURIWithFlags(aURIs[0], {
+ flags, postData: aPostDatas[0]
+ });
} catch (e) {
// Ignore failure in case a URI is wrong, so we can continue
// opening the next ones.
}
+ } else {
+ firstTabAdded = this.addTab(aURIs[0], {
+ ownerTab: owner,
+ skipAnimation: multiple,
+ allowThirdPartyFixup: aAllowThirdPartyFixup,
+ postData: aPostDatas[0],
+ userContextId: aUserContextId
+ });
+ if (aNewIndex !== -1) {
+ this.moveTabTo(firstTabAdded, aNewIndex);
+ targetTabIndex = firstTabAdded._tPos;
+ }
}
- else
- firstTabAdded = this.addTab(aURIs[0], {ownerTab: owner, skipAnimation: multiple});
- var tabNum = this.tabContainer.selectedIndex;
+ let tabNum = targetTabIndex;
for (let i = 1; i < aURIs.length; ++i) {
- let tab = this.addTab(aURIs[i], {skipAnimation: true});
- if (aReplace)
+ let tab = this.addTab(aURIs[i], {
+ skipAnimation: true,
+ allowThirdPartyFixup: aAllowThirdPartyFixup,
+ postData: aPostDatas[i],
+ userContextId: aUserContextId
+ });
+ if (targetTabIndex !== -1)
this.moveTabTo(tab, ++tabNum);
}
@@ -2976,10 +3016,6 @@
]]></body>
</method>
- <property name="userTypedClear"
- onget="return this.mCurrentBrowser.userTypedClear;"
- onset="return this.mCurrentBrowser.userTypedClear = val;"/>
-
<property name="userTypedValue"
onget="return this.mCurrentBrowser.userTypedValue;"
onset="return this.mCurrentBrowser.userTypedValue = val;"/>
@@ -4456,40 +4492,35 @@
this.tabbrowser.updateCurrentBrowser(true);
} else {
// Pass true to disallow dropping javascript: or data: urls
- let url;
+ let links;
try {
- url = browserDragAndDrop.drop(event, { }, true);
+ links = browserDragAndDrop.dropLinks(event, true);
} catch (ex) {}
// // valid urls don't contain spaces ' '; if we have a space it isn't a valid url.
// if (!url || url.includes(" ")) //PMed
- if (!url) //FF
+ if (!links || links.length === 0) //FF
return;
- let bgLoad = Services.prefs.getBoolPref("browser.tabs.loadInBackground");
+ let inBackground = Services.prefs.getBoolPref("browser.tabs.loadInBackground");
if (event.shiftKey)
- bgLoad = !bgLoad;
+ inBackground = !inBackground;
- let tab = this._getDragTargetTab(event);
- if (!tab || dropEffect == "copy") {
- // We're adding a new tab.
- let newIndex = this._getDropIndex(event);
- let newTab = this.tabbrowser.loadOneTab(url, {inBackground: bgLoad, allowThirdPartyFixup: true});
- this.tabbrowser.moveTabTo(newTab, newIndex);
- } else {
- // Load in an existing tab.
- try {
- let webNav = Ci.nsIWebNavigation;
- let flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
- webNav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
- this.tabbrowser.getBrowserForTab(tab).loadURIWithFlags(url, flags);
- if (!bgLoad)
- this.selectedItem = tab;
- } catch(ex) {
- // Just ignore invalid urls
- }
- }
+ let targetTab = this._getDragTargetTab(event);
+ let userContextId = this.selectedItem
+ .getAttribute("usercontextid") || 0;
+ let replace = !(!targetTab || dropEffect == "copy");
+ let newIndex = this._getDropIndex(event);
+ let urls = links.map(link => link.url);
+ this.tabbrowser.loadTabs(urls, {
+ inBackground,
+ replace,
+ allowThirdPartyFixup: true,
+ targetTab,
+ newIndex,
+ userContextId,
+ });
}
if (draggedTab) {
diff --git a/application/palemoon/base/content/urlbarBindings.xml b/application/palemoon/base/content/urlbarBindings.xml
index 4a6cfeee5..985769ec2 100644
--- a/application/palemoon/base/content/urlbarBindings.xml
+++ b/application/palemoon/base/content/urlbarBindings.xml
@@ -263,6 +263,9 @@
var postData = null;
var action = this._parseActionUrl(url);
+ let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange;
+
+ let matchLastLocationChange = true;
if (action) {
url = action.param;
if (this.hasAttribute("actiontype")) {
@@ -275,82 +278,94 @@
}
return;
}
+ continueOperation.call(this);
}
else {
- [url, postData, mayInheritPrincipal] = this._canonizeURL(aTriggeringEvent);
- if (!url)
- return;
- }
-
- this.value = url;
- gBrowser.userTypedValue = url;
- try {
- addToUrlbarHistory(url);
- } catch (ex) {
- // Things may go wrong when adding url to session history,
- // but don't let that interfere with the loading of the url.
- Cu.reportError(ex);
+ this._canonizeURL(aTriggeringEvent, response => {
+ [url, postData, mayInheritPrincipal] = response;
+ if (url) {
+ matchLastLocationChange = (lastLocationChange ==
+ gBrowser.selectedBrowser.lastLocationChange);
+ continueOperation.call(this);
+ }
+ });
}
- function loadCurrent() {
- let webnav = Ci.nsIWebNavigation;
- let flags = webnav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
- webnav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
- // Pass LOAD_FLAGS_DISALLOW_INHERIT_OWNER to prevent any loads from
- // inheriting the currently loaded document's principal, unless this
- // URL is marked as safe to inherit (e.g. came from a bookmark
- // keyword).
- if (!mayInheritPrincipal)
- flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER;
- gBrowser.loadURIWithFlags(url, flags, null, null, postData);
- }
+ function continueOperation()
+ {
+ this.value = url;
+ gBrowser.userTypedValue = url;
+ try {
+ addToUrlbarHistory(url);
+ } catch (ex) {
+ // Things may go wrong when adding url to session history,
+ // but don't let that interfere with the loading of the url.
+ Cu.reportError(ex);
+ }
- // Focus the content area before triggering loads, since if the load
- // occurs in a new tab, we want focus to be restored to the content
- // area when the current tab is re-selected.
- gBrowser.selectedBrowser.focus();
+ function loadCurrent() {
+ let flags = Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
+ // Pass LOAD_FLAGS_DISALLOW_INHERIT_OWNER to prevent any loads from
+ // inheriting the currently loaded document's principal, unless this
+ // URL is marked as safe to inherit (e.g. came from a bookmark
+ // keyword).
+ if (!mayInheritPrincipal)
+ flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER;
+ // If the value wasn't typed, we know that we decoded the value as
+ // UTF-8 (see losslessDecodeURI)
+ if (!this.valueIsTyped)
+ flags |= Ci.nsIWebNavigation.LOAD_FLAGS_URI_IS_UTF8;
+ gBrowser.loadURIWithFlags(url, flags, null, null, postData);
+ }
- let isMouseEvent = aTriggeringEvent instanceof MouseEvent;
- let altEnter = !isMouseEvent && aTriggeringEvent && aTriggeringEvent.altKey;
+ // Focus the content area before triggering loads, since if the load
+ // occurs in a new tab, we want focus to be restored to the content
+ // area when the current tab is re-selected.
+ gBrowser.selectedBrowser.focus();
- if (altEnter) {
- // XXX This was added a long time ago, and I'm not sure why it is
- // necessary. Alt+Enter's default action might cause a system beep,
- // or something like that?
- aTriggeringEvent.preventDefault();
- aTriggeringEvent.stopPropagation();
- }
+ let isMouseEvent = aTriggeringEvent instanceof MouseEvent;
- // If the current tab is empty, ignore Alt+Enter (just reuse this tab)
- altEnter = altEnter && !isTabEmpty(gBrowser.selectedTab);
+ // If the current tab is empty, ignore Alt+Enter (just reuse this tab)
+ let altEnter = !isMouseEvent && aTriggeringEvent &&
+ aTriggeringEvent.altKey && !isTabEmpty(gBrowser.selectedTab);
- if (isMouseEvent || altEnter) {
- // Use the standard UI link behaviors for clicks or Alt+Enter
- let where = "tab";
- if (isMouseEvent)
- where = whereToOpenLink(aTriggeringEvent, false, false);
+ if (isMouseEvent || altEnter) {
+ // Use the standard UI link behaviors for clicks or Alt+Enter
+ let where = "tab";
+ if (isMouseEvent)
+ where = whereToOpenLink(aTriggeringEvent, false, false);
- if (where == "current") {
- loadCurrent();
+ if (where == "current") {
+ if (matchLastLocationChange) {
+ loadCurrent();
+ }
+ } else {
+ this.handleRevert();
+ let params = { allowThirdPartyFixup: true,
+ postData: postData,
+ initiatingDoc: document };
+ if (!this.valueIsTyped)
+ params.isUTF8 = true;
+ openUILinkIn(url, where, params);
+ }
} else {
- this.handleRevert();
- let params = { allowThirdPartyFixup: true,
- postData: postData,
- initiatingDoc: document };
- openUILinkIn(url, where, params);
+ if (matchLastLocationChange) {
+ loadCurrent();
+ }
}
- } else {
- loadCurrent();
}
]]></body>
</method>
<method name="_canonizeURL">
<parameter name="aTriggeringEvent"/>
+ <parameter name="aCallback"/>
<body><![CDATA[
var url = this.value;
- if (!url)
- return ["", null, false];
+ if (!url) {
+ aCallback(["", null, false]);
+ return;
+ }
// Only add the suffix when the URL bar value isn't already "URL-like",
// and only if we get a keyboard event, to match user expectations.
@@ -403,11 +418,9 @@
}
}
- var postData = {};
- var mayInheritPrincipal = { value: false };
- url = getShortcutOrURI(url, postData, mayInheritPrincipal);
-
- return [url, postData.value, mayInheritPrincipal.value];
+ getShortcutOrURIAndPostData(url).then(data => {
+ aCallback([data.url, data.postData, data.mayInheritPrincipal]);
+ });
]]></body>
</method>
@@ -442,11 +455,12 @@
<method name="onDrop">
<parameter name="aEvent"/>
<body><![CDATA[
- let url = browserDragAndDrop.drop(aEvent, { })
+ let links = browserDragAndDrop.dropLinks(aEvent);
// The URL bar automatically handles inputs with newline characters,
// so we can get away with treating text/x-moz-url flavours as text/plain.
- if (url) {
+ if (links.length > 0 && links[0].url) {
+ let url = links[0].url;
aEvent.preventDefault();
this.value = url;
SetPageProxyState("invalid");
diff --git a/application/palemoon/components/downloads/content/allDownloadsViewOverlay.js b/application/palemoon/components/downloads/content/allDownloadsViewOverlay.js
index 46e867068..054f0405f 100644
--- a/application/palemoon/components/downloads/content/allDownloadsViewOverlay.js
+++ b/application/palemoon/components/downloads/content/allDownloadsViewOverlay.js
@@ -41,22 +41,6 @@ const DOWNLOAD_VIEW_SUPPORTED_COMMANDS =
const NOT_AVAILABLE = Number.MAX_VALUE;
/**
- * Download a URL.
- *
- * @param aURL
- * the url to download (nsIURI object)
- * @param [optional] aFileName
- * the destination file name
- */
-function DownloadURL(aURL, aFileName) {
- // For private browsing, try to get document out of the most recent browser
- // window, or provide our own if there's no browser window.
- let browserWin = RecentWindow.getMostRecentBrowserWindow();
- let initiatingDoc = browserWin ? browserWin.document : document;
- saveURL(aURL, aFileName, null, true, true, undefined, initiatingDoc);
-}
-
-/**
* A download element shell is responsible for handling the commands and the
* displayed data for a single download view element. The download element
* could represent either a past download (for which we get data from places) or
@@ -654,7 +638,10 @@ DownloadElementShell.prototype = {
// In future we may try to download into the same original target uri, when
// we have it. Though that requires verifying the path is still valid and
// may surprise the user if he wants to be requested every time.
- DownloadURL(this.downloadURI, this.getDownloadMetaData().fileName);
+ let browserWin = RecentWindow.getMostRecentBrowserWindow();
+ let initiatingDoc = browserWin ? browserWin.document : document;
+ DownloadURL(this.downloadURI, this.getDownloadMetaData().fileName,
+ initiatingDoc);
},
/* nsIController */
@@ -1407,16 +1394,11 @@ DownloadsPlacesView.prototype = {
_copySelectedDownloadsToClipboard:
function DPV__copySelectedDownloadsToClipboard() {
- let selectedElements = this._richlistbox.selectedItems;
- // Tycho: let urls = [e._shell.downloadURI for each (e in selectedElements)];
- let urls = [];
-
- for each (e in selectedElements) {
- urls.push(e._shell.downloadURI);
- }
+ let urls = [for (element of this._richlistbox.selectedItems)
+ element._shell.downloadURI];
Cc["@mozilla.org/widget/clipboardhelper;1"].
- getService(Ci.nsIClipboardHelper).copyString(urls.join("\n"), document);
+ getService(Ci.nsIClipboardHelper).copyString(urls.join("\n"));
},
_getURLFromClipboardData: function DPV__getURLFromClipboardData() {
@@ -1450,10 +1432,16 @@ DownloadsPlacesView.prototype = {
_downloadURLFromClipboard: function DPV__downloadURLFromClipboard() {
let [url, name] = this._getURLFromClipboardData();
- DownloadURL(url, name);
+ let browserWin = RecentWindow.getMostRecentBrowserWindow();
+ let initiatingDoc = browserWin ? browserWin.document : document;
+ DownloadURL(url, name, initiatingDoc);
},
doCommand: function DPV_doCommand(aCommand) {
+ // Commands may be invoked with keyboard shortcuts even if disabled.
+ if (!this.isCommandEnabled(aCommand)) {
+ return;
+ }
switch (aCommand) {
case "cmd_copy":
this._copySelectedDownloadsToClipboard();
@@ -1504,6 +1492,11 @@ DownloadsPlacesView.prototype = {
else
contextMenu.removeAttribute("state");
+ if (state == nsIDM.DOWNLOAD_DOWNLOADING) {
+ // The resumable property of a download may change at any time, so
+ // ensure we update the related command now.
+ goUpdateCommand("downloadsCmd_pauseResume");
+ }
return true;
},
@@ -1594,10 +1587,16 @@ DownloadsPlacesView.prototype = {
if (dt.mozGetDataAt("application/x-moz-file", 0))
return;
- let name = { };
- let url = Services.droppedLinkHandler.dropLink(aEvent, name);
- if (url)
- DownloadURL(url, name.value);
+ let links = Services.droppedLinkHandler.dropLinks(aEvent);
+ if (!links.length)
+ return;
+ let browserWin = RecentWindow.getMostRecentBrowserWindow();
+ let initiatingDoc = browserWin ? browserWin.document : document;
+ for (let link of links) {
+ if (link.url.startsWith("about:"))
+ continue;
+ DownloadURL(link.url, link.name, initiatingDoc);
+ }
}
};
diff --git a/application/palemoon/components/downloads/content/downloads.js b/application/palemoon/components/downloads/content/downloads.js
index 0412344bc..833d7d72f 100644
--- a/application/palemoon/components/downloads/content/downloads.js
+++ b/application/palemoon/components/downloads/content/downloads.js
@@ -507,8 +507,7 @@ const DownloadsPanel = {
let uri = NetUtil.newURI(url);
DownloadsCommon.log("Pasted URL seems valid. Starting download.");
- saveURL(uri.spec, name || uri.spec, null, true, true,
- undefined, document);
+ DownloadURL(uri.spec, name, document);
} catch (ex) {}
},
diff --git a/application/palemoon/components/downloads/content/indicator.js b/application/palemoon/components/downloads/content/indicator.js
index e6a5bd012..1a2175a92 100644
--- a/application/palemoon/components/downloads/content/indicator.js
+++ b/application/palemoon/components/downloads/content/indicator.js
@@ -548,15 +548,18 @@ const DownloadsIndicatorView = {
if (dt.mozGetDataAt("application/x-moz-file", 0))
return;
- let name = {};
- let url = browserDragAndDrop.drop(aEvent, name);
- if (url) {
- if (url.startsWith("about:")) {
- return;
- }
-
- let sourceDoc = dt.mozSourceNode ? dt.mozSourceNode.ownerDocument : document;
- saveURL(url, name.value, null, true, true, null, sourceDoc);
+ let links = browserDragAndDrop.dropLinks(aEvent);
+ if (!links.length)
+ return;
+ let sourceDoc = dt.mozSourceNode ? dt.mozSourceNode.ownerDocument : document;
+ let handled = false;
+ for (let link of links) {
+ if (link.url.startsWith("about:"))
+ continue;
+ saveURL(link.url, link.name, null, true, true, null, sourceDoc);
+ handled = true;
+ }
+ if (handled) {
aEvent.preventDefault();
}
},
diff --git a/application/palemoon/components/sessionstore/SessionStore.jsm b/application/palemoon/components/sessionstore/SessionStore.jsm
index f7c495be8..b8d126e21 100644
--- a/application/palemoon/components/sessionstore/SessionStore.jsm
+++ b/application/palemoon/components/sessionstore/SessionStore.jsm
@@ -1951,7 +1951,13 @@ var SessionStoreInternal = {
// userTypedValue.
if (browser.userTypedValue) {
tabData.userTypedValue = browser.userTypedValue;
- tabData.userTypedClear = browser.userTypedClear;
+ // We always used to keep track of the loading state as an integer, where
+ // '0' indicated the user had typed since the last load (or no load was
+ // ongoing), and any positive value indicated we had started a load since
+ // the last time the user typed in the URL bar. Mimic this to keep the
+ // session store representation in sync, even though we now represent this
+ // more explicitly:
+ tabData.userTypedClear = browser.didStartLoadSinceLastUserTyping() ? 1 : 0;
} else {
delete tabData.userTypedValue;
delete tabData.userTypedClear;
diff --git a/application/palemoon/locales/en-US/chrome/browser/browser.properties b/application/palemoon/locales/en-US/chrome/browser/browser.properties
index 2468f3c48..7f1c88a88 100644
--- a/application/palemoon/locales/en-US/chrome/browser/browser.properties
+++ b/application/palemoon/locales/en-US/chrome/browser/browser.properties
@@ -7,6 +7,7 @@ openFile=Open File
droponhometitle=Set Home Page
droponhomemsg=Do you want this document to be your new home page?
+droponhomemsgMultiple=Do you want these documents to be your new home pages?
# context menu strings
diff --git a/devtools/client/shared/widgets/TableWidget.js b/devtools/client/shared/widgets/TableWidget.js
index a0f0dfc11..57d2914d5 100644
--- a/devtools/client/shared/widgets/TableWidget.js
+++ b/devtools/client/shared/widgets/TableWidget.js
@@ -463,7 +463,14 @@ TableWidget.prototype = {
return;
}
- let selectedCell = this.tbody.querySelector(".theme-selected");
+ // We need to get the first *visible* selected cell. Some columns are hidden
+ // e.g. because they contain a unique compound key for cookies that is never
+ // displayed in the UI. To do this we get all selected cells and filter out
+ // any that are hidden.
+ let selectedCells = [...this.tbody.querySelectorAll(".theme-selected")]
+ .filter(cell => cell.clientWidth > 0);
+ // Select the first visible selected cell.
+ let selectedCell = selectedCells[0];
if (!selectedCell) {
return;
}
diff --git a/devtools/client/storage/ui.js b/devtools/client/storage/ui.js
index 7745c8da9..5bd29d297 100644
--- a/devtools/client/storage/ui.js
+++ b/devtools/client/storage/ui.js
@@ -482,24 +482,27 @@ StorageUI.prototype = {
* @param {object} See onUpdate docs
*/
handleChangedItems: function (changed) {
- if (this.tree.selectedItem) {
- let [type, host, db, objectStore] = this.tree.selectedItem;
- if (!changed[type] || !changed[type][host] ||
- changed[type][host].length == 0) {
- return;
- }
- try {
- let toUpdate = [];
- for (let name of changed[type][host]) {
- let names = JSON.parse(name);
- if (names[0] == db && names[1] == objectStore && names[2]) {
- toUpdate.push(name);
- }
+ let selectedItem = this.tree.selectedItem;
+ if (!selectedItem) {
+ return;
+ }
+
+ let [type, host, db, objectStore] = selectedItem;
+ if (!changed[type] || !changed[type][host] ||
+ changed[type][host].length == 0) {
+ return;
+ }
+ try {
+ let toUpdate = [];
+ for (let name of changed[type][host]) {
+ let names = JSON.parse(name);
+ if (names[0] == db && names[1] == objectStore && names[2]) {
+ toUpdate.push(name);
}
- this.fetchStorageObjects(type, host, toUpdate, REASON.UPDATE);
- } catch (ex) {
- this.fetchStorageObjects(type, host, changed[type][host], REASON.UPDATE);
}
+ this.fetchStorageObjects(type, host, toUpdate, REASON.UPDATE);
+ } catch (ex) {
+ this.fetchStorageObjects(type, host, changed[type][host], REASON.UPDATE);
}
},
@@ -830,6 +833,7 @@ StorageUI.prototype = {
if (!item) {
return;
}
+
this.table.clear();
this.hideSidebar();
this.searchBox.value = "";
@@ -1136,11 +1140,13 @@ StorageUI.prototype = {
* Handles adding an item from the storage
*/
onAddItem: function () {
- if (!this.tree.selectedItem) {
+ let selectedItem = this.tree.selectedItem;
+ if (!selectedItem) {
return;
}
+
let front = this.getCurrentFront();
- let [, host] = this.tree.selectedItem;
+ let [, host] = selectedItem;
// Prepare to scroll into view.
this.table.scrollIntoViewOnUpdate = true;