mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Merge f-t to m-c
This commit is contained in:
commit
1a9ee616c1
@ -571,7 +571,7 @@
|
||||
onclick="gPopupBlockerObserver.onReportButtonClick(event);"/>
|
||||
<image id="star-button"
|
||||
class="urlbar-icon"
|
||||
onclick="BookmarkingUI.onCommand(event);"/>
|
||||
onclick="if (event.button === 0) BookmarkingUI.onCommand(event);"/>
|
||||
<image id="go-button"
|
||||
class="urlbar-icon"
|
||||
tooltiptext="&goEndCap.tooltip;"
|
||||
|
@ -64,7 +64,7 @@ function test() {
|
||||
|
||||
MockFilePicker.returnFiles = [aFile];
|
||||
MockFilePicker.displayDirectory = null;
|
||||
aWin.getTargetFile(params, function() {
|
||||
aWin.promiseTargetFile(params).then(function() {
|
||||
// File picker should start with expected display dir.
|
||||
is(MockFilePicker.displayDirectory.path, aDisplayDir.path,
|
||||
"File picker should start with browser.download.lastDir");
|
||||
@ -78,7 +78,7 @@ function test() {
|
||||
gDownloadLastDir.cleanupPrivateFile();
|
||||
aWin.close();
|
||||
aCallback();
|
||||
});
|
||||
}).then(null, function() { ok(false); });
|
||||
}
|
||||
|
||||
testOnWindow(false, function(win, downloadDir) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 0.8.629
|
||||
Current extension version is: 0.8.641
|
||||
|
||||
|
@ -20,8 +20,8 @@ if (typeof PDFJS === 'undefined') {
|
||||
(typeof window !== 'undefined' ? window : this).PDFJS = {};
|
||||
}
|
||||
|
||||
PDFJS.version = '0.8.629';
|
||||
PDFJS.build = 'b16b3be';
|
||||
PDFJS.version = '0.8.641';
|
||||
PDFJS.build = '19485c3';
|
||||
|
||||
(function pdfjsWrapper() {
|
||||
// Use strict in our context only - users might not want it
|
||||
@ -6575,6 +6575,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
var bounds = Util.getAxialAlignedBoundingBox(
|
||||
group.bbox,
|
||||
currentCtx.mozCurrentTransform);
|
||||
// Clip the bounding box to the current canvas.
|
||||
bounds = Util.intersect(bounds, [0,
|
||||
0,
|
||||
currentCtx.canvas.width,
|
||||
currentCtx.canvas.height]);
|
||||
// Use ceil in case we're between sizes so we don't create canvas that is
|
||||
// too small and make the canvas at least 1x1 pixels.
|
||||
var drawnWidth = Math.max(Math.ceil(bounds[2] - bounds[0]), 1);
|
||||
|
@ -20,8 +20,8 @@ if (typeof PDFJS === 'undefined') {
|
||||
(typeof window !== 'undefined' ? window : this).PDFJS = {};
|
||||
}
|
||||
|
||||
PDFJS.version = '0.8.629';
|
||||
PDFJS.build = 'b16b3be';
|
||||
PDFJS.version = '0.8.641';
|
||||
PDFJS.build = '19485c3';
|
||||
|
||||
(function pdfjsWrapper() {
|
||||
// Use strict in our context only - users might not want it
|
||||
|
@ -223,7 +223,7 @@ limitations under the License.
|
||||
data-l10n-id="page_rotate_ccw"></menuitem>
|
||||
</menu>
|
||||
|
||||
<div id="viewerContainer">
|
||||
<div id="viewerContainer" tabindex="0">
|
||||
<div id="viewer"></div>
|
||||
</div>
|
||||
|
||||
|
@ -1299,11 +1299,12 @@ var SecondaryToolbar = {
|
||||
|
||||
initialize: function secondaryToolbarInitialize(options) {
|
||||
this.toolbar = options.toolbar;
|
||||
this.presentationMode = options.presentationMode;
|
||||
this.buttonContainer = this.toolbar.firstElementChild;
|
||||
|
||||
// Define the toolbar buttons.
|
||||
this.toggleButton = options.toggleButton;
|
||||
this.presentationMode = options.presentationMode;
|
||||
this.presentationModeButton = options.presentationModeButton;
|
||||
this.openFile = options.openFile;
|
||||
this.print = options.print;
|
||||
this.download = options.download;
|
||||
@ -1315,7 +1316,8 @@ var SecondaryToolbar = {
|
||||
// Attach the event listeners.
|
||||
var elements = [
|
||||
{ element: this.toggleButton, handler: this.toggle },
|
||||
{ element: this.presentationMode, handler: this.presentationModeClick },
|
||||
{ element: this.presentationModeButton,
|
||||
handler: this.presentationModeClick },
|
||||
{ element: this.openFile, handler: this.openFileClick },
|
||||
{ element: this.print, handler: this.printClick },
|
||||
{ element: this.download, handler: this.downloadClick },
|
||||
@ -1335,7 +1337,7 @@ var SecondaryToolbar = {
|
||||
|
||||
// Event handling functions.
|
||||
presentationModeClick: function secondaryToolbarPresentationModeClick(evt) {
|
||||
PresentationMode.request();
|
||||
this.presentationMode.request();
|
||||
this.close();
|
||||
},
|
||||
|
||||
@ -1372,7 +1374,7 @@ var SecondaryToolbar = {
|
||||
|
||||
// Misc. functions for interacting with the toolbar.
|
||||
setMaxHeight: function secondaryToolbarSetMaxHeight(container) {
|
||||
if (!container) {
|
||||
if (!container || !this.buttonContainer) {
|
||||
return;
|
||||
}
|
||||
this.newContainerHeight = container.clientHeight;
|
||||
@ -1410,10 +1412,6 @@ var SecondaryToolbar = {
|
||||
} else {
|
||||
this.open();
|
||||
}
|
||||
},
|
||||
|
||||
get isOpen() {
|
||||
return this.opened;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1506,6 +1504,8 @@ var PresentationMode = {
|
||||
this.container = options.container;
|
||||
this.secondaryToolbar = options.secondaryToolbar;
|
||||
|
||||
this.viewer = this.container.firstElementChild;
|
||||
|
||||
this.firstPage = options.firstPage;
|
||||
this.lastPage = options.lastPage;
|
||||
this.pageRotateCw = options.pageRotateCw;
|
||||
@ -1538,7 +1538,8 @@ var PresentationMode = {
|
||||
},
|
||||
|
||||
request: function presentationModeRequest() {
|
||||
if (!PDFView.supportsFullscreen || this.isFullscreen) {
|
||||
if (!PDFView.supportsFullscreen || this.isFullscreen ||
|
||||
!this.viewer.hasChildNodes()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1720,8 +1721,10 @@ var PDFView = {
|
||||
|
||||
SecondaryToolbar.initialize({
|
||||
toolbar: document.getElementById('secondaryToolbar'),
|
||||
presentationMode: PresentationMode,
|
||||
toggleButton: document.getElementById('secondaryToolbarToggle'),
|
||||
presentationMode: document.getElementById('secondaryPresentationMode'),
|
||||
presentationModeButton:
|
||||
document.getElementById('secondaryPresentationMode'),
|
||||
openFile: document.getElementById('secondaryOpenFile'),
|
||||
print: document.getElementById('secondaryPrint'),
|
||||
download: document.getElementById('secondaryDownload'),
|
||||
@ -1968,8 +1971,8 @@ var PDFView = {
|
||||
},
|
||||
|
||||
get isHorizontalScrollbarEnabled() {
|
||||
var div = document.getElementById('viewerContainer');
|
||||
return div.scrollWidth > div.clientWidth;
|
||||
return (PresentationMode.active ? false :
|
||||
(this.container.scrollWidth > this.container.clientWidth));
|
||||
},
|
||||
|
||||
initPassiveLoading: function pdfViewInitPassiveLoading() {
|
||||
@ -3230,6 +3233,7 @@ var PageView = function pageView(container, id, scale,
|
||||
this.scrollIntoView = function pageViewScrollIntoView(dest) {
|
||||
if (PresentationMode.active) { // Avoid breaking presentation mode.
|
||||
dest = null;
|
||||
PDFView.setScale(PDFView.currentScaleValue, true, true);
|
||||
}
|
||||
if (!dest) {
|
||||
scrollIntoView(div);
|
||||
@ -4554,7 +4558,7 @@ window.addEventListener('DOMMouseScroll', function(evt) {
|
||||
|
||||
window.addEventListener('click', function click(evt) {
|
||||
if (!PresentationMode.active) {
|
||||
if (SecondaryToolbar.isOpen && PDFView.container.contains(evt.target)) {
|
||||
if (SecondaryToolbar.opened && PDFView.container.contains(evt.target)) {
|
||||
SecondaryToolbar.close();
|
||||
}
|
||||
} else if (evt.button === 0) {
|
||||
@ -4649,6 +4653,9 @@ window.addEventListener('keydown', function keydown(evt) {
|
||||
return; // ignoring if the 'toolbar' element is focused
|
||||
curElement = curElement.parentNode;
|
||||
}
|
||||
// Workaround for issue in Firefox, that prevents scroll keys from working
|
||||
// when elements with 'tabindex' are focused.
|
||||
PDFView.container.blur();
|
||||
|
||||
if (cmd === 0) { // no control key pressed at all.
|
||||
switch (evt.keyCode) {
|
||||
@ -4673,7 +4680,7 @@ window.addEventListener('keydown', function keydown(evt) {
|
||||
handled = true;
|
||||
break;
|
||||
case 27: // esc key
|
||||
if (SecondaryToolbar.isOpen) {
|
||||
if (SecondaryToolbar.opened) {
|
||||
SecondaryToolbar.close();
|
||||
handled = true;
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
chrome.manifest
|
||||
components/PdfRedirector.js
|
||||
components/PdfStreamConverter.js
|
||||
content/PdfJs.jsm
|
||||
content/PdfJsTelemetry.jsm
|
||||
content/build/pdf.js
|
||||
content/build/pdf.worker.js
|
||||
content/network.js
|
||||
content/PdfJs.jsm
|
||||
content/PdfJsTelemetry.jsm
|
||||
content/web/debugger.js
|
||||
content/web/images/annotation-check.svg
|
||||
content/web/images/annotation-comment.svg
|
||||
|
@ -49,8 +49,12 @@ public:
|
||||
|
||||
bool Headphones() const
|
||||
{
|
||||
MOZ_ASSERT(mState != hal::SWITCH_STATE_UNKNOWN);
|
||||
return mState != hal::SWITCH_STATE_OFF;
|
||||
// Bug 929139 - Remove the assert check for SWITCH_STATE_UNKNOWN.
|
||||
// If any devices (ex: emulator) didn't have the corresponding sys node for
|
||||
// headset switch state then GonkSwitch will report the unknown state.
|
||||
// So it is possible to get unknown state here.
|
||||
return mState != hal::SWITCH_STATE_OFF &&
|
||||
mState != hal::SWITCH_STATE_UNKNOWN;
|
||||
}
|
||||
|
||||
bool SetVolumeControlChannel(const nsAString& aChannel);
|
||||
|
@ -304,29 +304,33 @@ AbstractFile.normalizeOpenMode = function normalizeOpenMode(mode) {
|
||||
write: false,
|
||||
trunc: false,
|
||||
create: false,
|
||||
existing: false
|
||||
existing: false,
|
||||
append: true
|
||||
};
|
||||
for (let key in mode) {
|
||||
if (!mode[key]) continue; // Only interpret true-ish keys
|
||||
let val = !!mode[key]; // bool cast.
|
||||
switch (key) {
|
||||
case "read":
|
||||
result.read = true;
|
||||
result.read = val;
|
||||
break;
|
||||
case "write":
|
||||
result.write = true;
|
||||
result.write = val;
|
||||
break;
|
||||
case "truncate": // fallthrough
|
||||
case "trunc":
|
||||
result.trunc = true;
|
||||
result.write = true;
|
||||
result.trunc = val;
|
||||
result.write |= val;
|
||||
break;
|
||||
case "create":
|
||||
result.create = true;
|
||||
result.write = true;
|
||||
result.create = val;
|
||||
result.write |= val;
|
||||
break;
|
||||
case "existing": // fallthrough
|
||||
case "exist":
|
||||
result.existing = true;
|
||||
result.existing = val;
|
||||
break;
|
||||
case "append":
|
||||
result.append = val;
|
||||
break;
|
||||
default:
|
||||
throw new TypeError("Mode " + key + " not understood");
|
||||
|
@ -203,8 +203,11 @@
|
||||
* on the other fields of |mode|.
|
||||
* - {bool} write If |true|, the file will be opened for
|
||||
* writing. The file may also be opened for reading, depending
|
||||
* on the other fields of |mode|. If neither |truncate| nor
|
||||
* |create| is specified, the file is opened for appending.
|
||||
* on the other fields of |mode|.
|
||||
* - {bool} append If |true|, the file will be opened for appending,
|
||||
* meaning the equivalent of |.setPosition(0, POS_END)| is executed
|
||||
* before each write. The default is |true|, i.e. opening a file for
|
||||
* appending. Specify |append: false| to open the file in regular mode.
|
||||
*
|
||||
* If neither |truncate|, |create| or |write| is specified, the file
|
||||
* is opened for reading.
|
||||
@ -251,12 +254,11 @@
|
||||
flags |= Const.O_CREAT | Const.O_EXCL;
|
||||
} else if (mode.read && !mode.write) {
|
||||
// flags are sufficient
|
||||
} else /*append*/ {
|
||||
if (mode.existing) {
|
||||
flags |= Const.O_APPEND;
|
||||
} else {
|
||||
flags |= Const.O_APPEND | Const.O_CREAT;
|
||||
}
|
||||
} else if (!mode.existing) {
|
||||
flags |= Const.O_CREAT;
|
||||
}
|
||||
if (mode.append) {
|
||||
flags |= Const.O_APPEND;
|
||||
}
|
||||
}
|
||||
return error_or_file(UnixFile.open(path, flags, omode));
|
||||
@ -548,10 +550,12 @@
|
||||
let result;
|
||||
try {
|
||||
source = File.open(sourcePath);
|
||||
// Need to open the output file with |append:false|, or else |splice|
|
||||
// won't work.
|
||||
if (options.noOverwrite) {
|
||||
dest = File.open(destPath, {create:true});
|
||||
dest = File.open(destPath, {create:true, append:false});
|
||||
} else {
|
||||
dest = File.open(destPath, {trunc:true});
|
||||
dest = File.open(destPath, {trunc:true, append:false});
|
||||
}
|
||||
if (options.unixUserland) {
|
||||
result = pump_userland(source, dest, options);
|
||||
|
@ -134,6 +134,11 @@
|
||||
* @throws {OS.File.Error} In case of I/O error.
|
||||
*/
|
||||
File.prototype._write = function _write(buffer, nbytes, options) {
|
||||
if (this._appendMode) {
|
||||
// Need to manually seek on Windows, as O_APPEND is not supported.
|
||||
// This is, of course, a race, but there is no real way around this.
|
||||
this.setPosition(0, File.POS_END);
|
||||
}
|
||||
// |gBytesWrittenPtr| is a pointer to |gBytesWritten|.
|
||||
throw_on_zero("write",
|
||||
WinFile.WriteFile(this.fd, buffer, nbytes, gBytesWrittenPtr, null)
|
||||
@ -225,8 +230,11 @@
|
||||
* on the other fields of |mode|.
|
||||
* - {bool} write If |true|, the file will be opened for
|
||||
* writing. The file may also be opened for reading, depending
|
||||
* on the other fields of |mode|. If neither |truncate| nor
|
||||
* |create| is specified, the file is opened for appending.
|
||||
* on the other fields of |mode|.
|
||||
* - {bool} append If |true|, the file will be opened for appending,
|
||||
* meaning the equivalent of |.setPosition(0, POS_END)| is executed
|
||||
* before each write. The default is |true|, i.e. opening a file for
|
||||
* appending. Specify |append: false| to open the file in regular mode.
|
||||
*
|
||||
* If neither |truncate|, |create| or |write| is specified, the file
|
||||
* is opened for reading.
|
||||
@ -264,6 +272,9 @@
|
||||
let template = options.winTemplate ? options.winTemplate._fd : null;
|
||||
let access;
|
||||
let disposition;
|
||||
|
||||
mode = OS.Shared.AbstractFile.normalizeOpenMode(mode);
|
||||
|
||||
if ("winAccess" in options && "winDisposition" in options) {
|
||||
access = options.winAccess;
|
||||
disposition = options.winDisposition;
|
||||
@ -272,7 +283,6 @@
|
||||
throw new TypeError("OS.File.open requires either both options " +
|
||||
"winAccess and winDisposition or neither");
|
||||
} else {
|
||||
mode = OS.Shared.AbstractFile.normalizeOpenMode(mode);
|
||||
if (mode.read) {
|
||||
access |= Const.GENERIC_READ;
|
||||
}
|
||||
@ -293,16 +303,18 @@
|
||||
disposition = Const.CREATE_NEW;
|
||||
} else if (mode.read && !mode.write) {
|
||||
disposition = Const.OPEN_EXISTING;
|
||||
} else /*append*/ {
|
||||
if (mode.existing) {
|
||||
disposition = Const.OPEN_EXISTING;
|
||||
} else {
|
||||
disposition = Const.OPEN_ALWAYS;
|
||||
}
|
||||
} else if (mode.existing) {
|
||||
disposition = Const.OPEN_EXISTING;
|
||||
} else {
|
||||
disposition = Const.OPEN_ALWAYS;
|
||||
}
|
||||
}
|
||||
|
||||
let file = error_or_file(WinFile.CreateFile(path,
|
||||
access, share, security, disposition, flags, template));
|
||||
|
||||
file._appendMode = !!mode.append;
|
||||
|
||||
if (!(mode.trunc && mode.existing)) {
|
||||
return file;
|
||||
}
|
||||
|
@ -0,0 +1,122 @@
|
||||
"use strict";
|
||||
|
||||
do_print("starting tests");
|
||||
|
||||
Components.utils.import("resource://gre/modules/osfile.jsm");
|
||||
Components.utils.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
/**
|
||||
* A test to check that the |append| mode flag is correctly implemented.
|
||||
* (see bug 925865)
|
||||
*/
|
||||
|
||||
function setup_mode(mode) {
|
||||
// Complete mode.
|
||||
let realMode = {
|
||||
read: true,
|
||||
write: true
|
||||
};
|
||||
for (let k in mode) {
|
||||
realMode[k] = mode[k];
|
||||
}
|
||||
return realMode;
|
||||
}
|
||||
|
||||
// Test append mode.
|
||||
function test_append(mode) {
|
||||
let path = OS.Path.join(OS.Constants.Path.tmpDir,
|
||||
"test_osfile_async_append.tmp");
|
||||
|
||||
// Clear any left-over files from previous runs.
|
||||
try {
|
||||
yield OS.File.remove(path);
|
||||
} catch (ex if ex.becauseNoSuchFile) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
try {
|
||||
mode = setup_mode(mode);
|
||||
mode.append = true;
|
||||
if (mode.trunc) {
|
||||
// Pre-fill file with some data to see if |trunc| actually works.
|
||||
yield OS.File.writeAtomic(path, new Uint8Array(500));
|
||||
}
|
||||
let file = yield OS.File.open(path, mode);
|
||||
try {
|
||||
yield file.write(new Uint8Array(1000));
|
||||
yield file.setPosition(0, OS.File.POS_START);
|
||||
yield file.read(100);
|
||||
// Should be at offset 100, length 1000 now.
|
||||
yield file.write(new Uint8Array(100));
|
||||
// Should be at offset 1100, length 1100 now.
|
||||
let stat = yield file.stat();
|
||||
do_check_eq(1100, stat.size);
|
||||
} finally {
|
||||
yield file.close();
|
||||
}
|
||||
} catch(ex) {
|
||||
try {
|
||||
yield OS.File.remove(path);
|
||||
} catch (ex if ex.becauseNoSuchFile) {
|
||||
// ignore.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test no-append mode.
|
||||
function test_no_append(mode) {
|
||||
let path = OS.Path.join(OS.Constants.Path.tmpDir,
|
||||
"test_osfile_async_noappend.tmp");
|
||||
|
||||
// Clear any left-over files from previous runs.
|
||||
try {
|
||||
yield OS.File.remove(path);
|
||||
} catch (ex if ex.becauseNoSuchFile) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
try {
|
||||
mode = setup_mode(mode);
|
||||
mode.append = false;
|
||||
if (mode.trunc) {
|
||||
// Pre-fill file with some data to see if |trunc| actually works.
|
||||
yield OS.File.writeAtomic(path, new Uint8Array(500));
|
||||
}
|
||||
let file = yield OS.File.open(path, mode);
|
||||
try {
|
||||
yield file.write(new Uint8Array(1000));
|
||||
yield file.setPosition(0, OS.File.POS_START);
|
||||
yield file.read(100);
|
||||
// Should be at offset 100, length 1000 now.
|
||||
yield file.write(new Uint8Array(100));
|
||||
// Should be at offset 200, length 1000 now.
|
||||
let stat = yield file.stat();
|
||||
do_check_eq(1000, stat.size);
|
||||
} finally {
|
||||
yield file.close();
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
yield OS.File.remove(path);
|
||||
} catch (ex if ex.becauseNoSuchFile) {
|
||||
// ignore.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let test_flags = [
|
||||
{},
|
||||
{create:true},
|
||||
{trunc:true}
|
||||
];
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
|
||||
for (let t of test_flags) {
|
||||
add_task(test_append.bind(null, t));
|
||||
add_task(test_no_append.bind(null, t));
|
||||
}
|
||||
add_task(do_test_finished);
|
||||
|
||||
run_next_test();
|
||||
}
|
@ -5,6 +5,7 @@ tail =
|
||||
[test_osfile_closed.js]
|
||||
[test_path.js]
|
||||
[test_osfile_async.js]
|
||||
[test_osfile_async_append.js]
|
||||
[test_osfile_async_bytes.js]
|
||||
[test_osfile_async_copy.js]
|
||||
[test_profiledir.js]
|
||||
|
@ -3,9 +3,24 @@
|
||||
# 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://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
|
||||
"resource://gre/modules/Downloads.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadLastDir",
|
||||
"resource://gre/modules/DownloadLastDir.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "OS",
|
||||
"resource://gre/modules/osfile.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
"resource://gre/modules/Services.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
var ContentAreaUtils = {
|
||||
|
||||
// this is for backwards compatibility.
|
||||
@ -311,15 +326,15 @@ function internalSave(aURL, aDocument, aDefaultFileName, aContentDisposition,
|
||||
// Find a URI to use for determining last-downloaded-to directory
|
||||
let relatedURI = aReferrer || sourceURI;
|
||||
|
||||
getTargetFile(fpParams, function(aDialogCancelled) {
|
||||
if (aDialogCancelled)
|
||||
promiseTargetFile(fpParams, aSkipPrompt, relatedURI).then(aDialogAccepted => {
|
||||
if (!aDialogAccepted)
|
||||
return;
|
||||
|
||||
saveAsType = fpParams.saveAsType;
|
||||
file = fpParams.file;
|
||||
|
||||
continueSave();
|
||||
}, aSkipPrompt, relatedURI);
|
||||
}).then(null, Components.utils.reportError);
|
||||
}
|
||||
|
||||
function continueSave() {
|
||||
@ -527,10 +542,6 @@ function initFileInfo(aFI, aURL, aURLCharset, aDocument,
|
||||
* @param aFpP
|
||||
* A structure (see definition in internalSave(...) method)
|
||||
* containing all the data used within this method.
|
||||
* @param aCallback
|
||||
* A callback function that will be called once the function finishes.
|
||||
* The first argument passed to the function will be a boolean that,
|
||||
* when true, indicated that the user dismissed the file picker.
|
||||
* @param aSkipPrompt
|
||||
* If true, attempt to save the file automatically to the user's default
|
||||
* download directory, thus skipping the explicit prompt for a file name,
|
||||
@ -542,58 +553,59 @@ function initFileInfo(aFI, aURL, aURLCharset, aDocument,
|
||||
* An nsIURI associated with the download. The last used
|
||||
* directory of the picker is retrieved from/stored in the
|
||||
* Content Pref Service using this URI.
|
||||
* @return Promise
|
||||
* @resolve a boolean. When true, it indicates that the file picker dialog
|
||||
* is accepted.
|
||||
*/
|
||||
function getTargetFile(aFpP, aCallback, /* optional */ aSkipPrompt, /* optional */ aRelatedURI)
|
||||
function promiseTargetFile(aFpP, /* optional */ aSkipPrompt, /* optional */ aRelatedURI)
|
||||
{
|
||||
if (!getTargetFile.DownloadLastDir)
|
||||
Components.utils.import("resource://gre/modules/DownloadLastDir.jsm", getTargetFile);
|
||||
var gDownloadLastDir = new getTargetFile.DownloadLastDir(window);
|
||||
return Task.spawn(function() {
|
||||
let downloadLastDir = new DownloadLastDir(window);
|
||||
let prefBranch = Services.prefs.getBranch("browser.download.");
|
||||
let useDownloadDir = prefBranch.getBoolPref("useDownloadDir");
|
||||
|
||||
var prefs = Services.prefs.getBranch("browser.download.");
|
||||
var useDownloadDir = prefs.getBoolPref("useDownloadDir");
|
||||
const nsIFile = Components.interfaces.nsIFile;
|
||||
if (!aSkipPrompt)
|
||||
useDownloadDir = false;
|
||||
|
||||
if (!aSkipPrompt)
|
||||
useDownloadDir = false;
|
||||
// Default to the user's default downloads directory configured
|
||||
// through download prefs.
|
||||
let dirPath = yield Downloads.getPreferredDownloadsDirectory();
|
||||
let dirExists = yield OS.File.exists(dirPath);
|
||||
let dir = new FileUtils.File(dirPath);
|
||||
|
||||
// Default to the user's default downloads directory configured
|
||||
// through download prefs.
|
||||
var dir = Services.downloads.userDownloadsDirectory;
|
||||
var dirExists = dir && dir.exists();
|
||||
|
||||
if (useDownloadDir && dirExists) {
|
||||
dir.append(getNormalizedLeafName(aFpP.fileInfo.fileName,
|
||||
aFpP.fileInfo.fileExt));
|
||||
aFpP.file = uniqueFile(dir);
|
||||
aCallback(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// We must prompt for the file name explicitly.
|
||||
// If we must prompt because we were asked to...
|
||||
if (useDownloadDir) {
|
||||
// Keep async behavior in both branches
|
||||
Services.tm.mainThread.dispatch(function() {
|
||||
displayPicker();
|
||||
}, Components.interfaces.nsIThread.DISPATCH_NORMAL);
|
||||
} else {
|
||||
gDownloadLastDir.getFileAsync(aRelatedURI, function getFileAsyncCB(aFile) {
|
||||
if (aFile && aFile.exists()) {
|
||||
dir = aFile;
|
||||
dirExists = true;
|
||||
}
|
||||
displayPicker();
|
||||
});
|
||||
}
|
||||
|
||||
function displayPicker() {
|
||||
if (!dirExists) {
|
||||
// Default to desktop.
|
||||
dir = Services.dirsvc.get("Desk", nsIFile);
|
||||
if (useDownloadDir && dirExists) {
|
||||
dir.append(getNormalizedLeafName(aFpP.fileInfo.fileName,
|
||||
aFpP.fileInfo.fileExt));
|
||||
aFpP.file = uniqueFile(dir);
|
||||
throw new Task.Result(true);
|
||||
}
|
||||
|
||||
var fp = makeFilePicker();
|
||||
var titleKey = aFpP.fpTitleKey || "SaveLinkTitle";
|
||||
// We must prompt for the file name explicitly.
|
||||
// If we must prompt because we were asked to...
|
||||
let deferred = Promise.defer();
|
||||
if (useDownloadDir) {
|
||||
// Keep async behavior in both branches
|
||||
Services.tm.mainThread.dispatch(function() {
|
||||
deferred.resolve(null);
|
||||
}, Components.interfaces.nsIThread.DISPATCH_NORMAL);
|
||||
} else {
|
||||
downloadLastDir.getFileAsync(aRelatedURI, function getFileAsyncCB(aFile) {
|
||||
deferred.resolve(aFile);
|
||||
});
|
||||
}
|
||||
let file = yield deferred.promise;
|
||||
if (file && (yield OS.File.exists(file.path))) {
|
||||
dir = file;
|
||||
dirExists = true;
|
||||
}
|
||||
|
||||
if (!dirExists) {
|
||||
// Default to desktop.
|
||||
dir = Services.dirsvc.get("Desk", Components.interfaces.nsIFile);
|
||||
}
|
||||
|
||||
let fp = makeFilePicker();
|
||||
let titleKey = aFpP.fpTitleKey || "SaveLinkTitle";
|
||||
fp.init(window, ContentAreaUtils.stringBundle.GetStringFromName(titleKey),
|
||||
Components.interfaces.nsIFilePicker.modeSave);
|
||||
|
||||
@ -608,31 +620,35 @@ function getTargetFile(aFpP, aCallback, /* optional */ aSkipPrompt, /* optional
|
||||
// more than one filter in addition to "All Files".
|
||||
if (aFpP.saveMode != SAVEMODE_FILEONLY) {
|
||||
try {
|
||||
fp.filterIndex = prefs.getIntPref("save_converter_index");
|
||||
fp.filterIndex = prefBranch.getIntPref("save_converter_index");
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
if (fp.show() == Components.interfaces.nsIFilePicker.returnCancel || !fp.file) {
|
||||
aCallback(true);
|
||||
return;
|
||||
let deferComplete = Promise.defer();
|
||||
fp.open(function(aResult) {
|
||||
deferComplete.resolve(aResult);
|
||||
});
|
||||
let result = yield deferComplete.promise;
|
||||
if (result == Components.interfaces.nsIFilePicker.returnCancel || !fp.file) {
|
||||
throw new Task.Result(false);
|
||||
}
|
||||
|
||||
if (aFpP.saveMode != SAVEMODE_FILEONLY)
|
||||
prefs.setIntPref("save_converter_index", fp.filterIndex);
|
||||
prefBranch.setIntPref("save_converter_index", fp.filterIndex);
|
||||
|
||||
// Do not store the last save directory as a pref inside the private browsing mode
|
||||
var directory = fp.file.parent.QueryInterface(nsIFile);
|
||||
gDownloadLastDir.setFile(aRelatedURI, directory);
|
||||
downloadLastDir.setFile(aRelatedURI, fp.file.parent);
|
||||
|
||||
fp.file.leafName = validateFileName(fp.file.leafName);
|
||||
|
||||
aFpP.saveAsType = fp.filterIndex;
|
||||
aFpP.file = fp.file;
|
||||
aFpP.fileURL = fp.fileURL;
|
||||
aCallback(false);
|
||||
}
|
||||
|
||||
throw new Task.Result(true);
|
||||
});
|
||||
}
|
||||
|
||||
// Since we're automatically downloading, we don't get the file picker's
|
||||
|
@ -807,8 +807,7 @@
|
||||
|
||||
this.yearField = document.getAnonymousElementByAttribute(this, "anonid", yfield);
|
||||
if (!twoDigitYear)
|
||||
this.yearField.parentNode.className =
|
||||
"datetimepicker-input-subbox datetimepicker-year";
|
||||
this.yearField.parentNode.classList.add("datetimepicker-input-subbox", "datetimepicker-year");
|
||||
this.monthField = document.getAnonymousElementByAttribute(this, "anonid", mfield);
|
||||
this.dateField = document.getAnonymousElementByAttribute(this, "anonid", dfield);
|
||||
|
||||
@ -1178,7 +1177,7 @@
|
||||
return;
|
||||
|
||||
var target = event.originalTarget;
|
||||
if (target.className == "datepicker-gridlabel" &&
|
||||
if (target.classList.contains("datepicker-gridlabel") &&
|
||||
target != this.selectedItem) {
|
||||
this.selectedItem = target;
|
||||
this._dateValue = new Date(this._displayedDate);
|
||||
|
@ -220,11 +220,11 @@ Services.obs.addObserver(function observe(aSubject, aTopic, aValue) {
|
||||
return;
|
||||
}
|
||||
if (stack) {
|
||||
message += " at " + stack;
|
||||
message += "\nFull Stack: " + stack;
|
||||
}
|
||||
error.init(
|
||||
/*message*/"A promise chain failed to handle a rejection: on " +
|
||||
date + ", " + message,
|
||||
/*message*/"A promise chain failed to handle a rejection.\n\n" +
|
||||
"Date: " + date + "\nFull Message: " + message,
|
||||
/*sourceName*/ fileName,
|
||||
/*sourceLine*/ lineNumber?("" + lineNumber):0,
|
||||
/*lineNumber*/ lineNumber || 0,
|
||||
|
Loading…
Reference in New Issue
Block a user