Best JavaScript code snippet using playwright-internal
common_test_Download.js
Source:common_test_Download.js
1/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */2/* vim: set ts=2 et sw=2 tw=80: */3/* Any copyright is dedicated to the Public Domain.4 * http://creativecommons.org/publicdomain/zero/1.0/ */5/**6 * This script is loaded by "test_DownloadCore.js" and "test_DownloadLegacy.js"7 * with different values of the gUseLegacySaver variable, to apply tests to both8 * the "copy" and "legacy" saver implementations.9 */10"use strict";11////////////////////////////////////////////////////////////////////////////////12//// Globals13const kDeleteTempFileOnExit = "browser.helperApps.deleteTempFileOnExit";14/**15 * Creates and starts a new download, using either DownloadCopySaver or16 * DownloadLegacySaver based on the current test run.17 *18 * @return {Promise}19 * @resolves The newly created Download object. The download may be in progress20 * or already finished. The promiseDownloadStopped function can be21 * used to wait for completion.22 * @rejects JavaScript exception.23 */24function promiseStartDownload(aSourceUrl) {25 if (gUseLegacySaver) {26 return promiseStartLegacyDownload(aSourceUrl);27 }28 return promiseNewDownload(aSourceUrl).then(download => {29 download.start();30 return download;31 });32}33/**34 * Creates and starts a new download, configured to keep partial data, and35 * returns only when the first part of "interruptible_resumable.txt" has been36 * saved to disk. You must call "continueResponses" to allow the interruptible37 * request to continue.38 *39 * This function uses either DownloadCopySaver or DownloadLegacySaver based on40 * the current test run.41 *42 * @return {Promise}43 * @resolves The newly created Download object, still in progress.44 * @rejects JavaScript exception.45 */46function promiseStartDownload_tryToKeepPartialData() {47 return Task.spawn(function () {48 mustInterruptResponses();49 // Start a new download and configure it to keep partially downloaded data.50 let download;51 if (!gUseLegacySaver) {52 let targetFilePath = getTempFile(TEST_TARGET_FILE_NAME).path;53 download = yield Downloads.createDownload({54 source: httpUrl("interruptible_resumable.txt"),55 target: { path: targetFilePath,56 partFilePath: targetFilePath + ".part" },57 });58 download.tryToKeepPartialData = true;59 download.start();60 } else {61 // Start a download using nsIExternalHelperAppService, that is configured62 // to keep partially downloaded data by default.63 download = yield promiseStartExternalHelperAppServiceDownload();64 }65 yield promiseDownloadMidway(download);66 yield promisePartFileReady(download);67 throw new Task.Result(download);68 });69}70/**71 * This function should be called after the progress notification for a download72 * is received, and waits for the worker thread of BackgroundFileSaver to73 * receive the data to be written to the ".part" file on disk.74 *75 * @return {Promise}76 * @resolves When the ".part" file has been written to disk.77 * @rejects JavaScript exception.78 */79function promisePartFileReady(aDownload) {80 return Task.spawn(function () {81 // We don't have control over the file output code in BackgroundFileSaver.82 // After we receive the download progress notification, we may only check83 // that the ".part" file has been created, while its size cannot be84 // determined because the file is currently open.85 try {86 do {87 yield promiseTimeout(50);88 } while (!(yield OS.File.exists(aDownload.target.partFilePath)));89 } catch (ex if ex instanceof OS.File.Error) {90 // This indicates that the file has been created and cannot be accessed.91 // The specific error might vary with the platform.92 do_print("Expected exception while checking existence: " + ex.toString());93 // Wait some more time to allow the write to complete.94 yield promiseTimeout(100);95 }96 });97}98/**99 * Checks that the actual data written to disk matches the expected data as well100 * as the properties of the given DownloadTarget object.101 *102 * @param downloadTarget103 * The DownloadTarget object whose details have to be verified.104 * @param expectedContents105 * String containing the octets that are expected in the file.106 *107 * @return {Promise}108 * @resolves When the properties have been verified.109 * @rejects JavaScript exception.110 */111let promiseVerifyTarget = Task.async(function* (downloadTarget,112 expectedContents) {113 yield promiseVerifyContents(downloadTarget.path, expectedContents);114 do_check_true(downloadTarget.exists);115 do_check_eq(downloadTarget.size, expectedContents.length);116});117////////////////////////////////////////////////////////////////////////////////118//// Tests119/**120 * Executes a download and checks its basic properties after construction.121 * The download is started by constructing the simplest Download object with122 * the "copy" saver, or using the legacy nsITransfer interface.123 */124add_task(function test_basic()125{126 let targetFile = getTempFile(TEST_TARGET_FILE_NAME);127 let download;128 if (!gUseLegacySaver) {129 // When testing DownloadCopySaver, we have control over the download, thus130 // we can check its basic properties before it starts.131 download = yield Downloads.createDownload({132 source: { url: httpUrl("source.txt") },133 target: { path: targetFile.path },134 saver: { type: "copy" },135 });136 do_check_eq(download.source.url, httpUrl("source.txt"));137 do_check_eq(download.target.path, targetFile.path);138 yield download.start();139 } else {140 // When testing DownloadLegacySaver, the download is already started when it141 // is created, thus we must check its basic properties while in progress.142 download = yield promiseStartLegacyDownload(null,143 { targetFile: targetFile });144 do_check_eq(download.source.url, httpUrl("source.txt"));145 do_check_eq(download.target.path, targetFile.path);146 yield promiseDownloadStopped(download);147 }148 // Check additional properties on the finished download.149 do_check_true(download.source.referrer === null);150 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT);151});152/**153 * Executes a download with the tryToKeepPartialData property set, and ensures154 * that the file is saved correctly. When testing DownloadLegacySaver, the155 * download is executed using the nsIExternalHelperAppService component.156 */157add_task(function test_basic_tryToKeepPartialData()158{159 let download = yield promiseStartDownload_tryToKeepPartialData();160 continueResponses();161 yield promiseDownloadStopped(download);162 // The target file should now have been created, and the ".part" file deleted.163 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT);164 do_check_false(yield OS.File.exists(download.target.partFilePath));165 do_check_eq(32, download.saver.getSha256Hash().length);166});167/**168 * Tests the permissions of the final target file once the download finished.169 */170add_task(function test_unix_permissions()171{172 // This test is only executed on some Desktop systems.173 if (Services.appinfo.OS != "Darwin" && Services.appinfo.OS != "Linux" &&174 Services.appinfo.OS != "WINNT") {175 do_print("Skipping test.");176 return;177 }178 let launcherPath = getTempFile("app-launcher").path;179 for (let autoDelete of [false, true]) {180 for (let isPrivate of [false, true]) {181 for (let launchWhenSucceeded of [false, true]) {182 do_print("Checking " + JSON.stringify({ autoDelete,183 isPrivate,184 launchWhenSucceeded }));185 Services.prefs.setBoolPref(kDeleteTempFileOnExit, autoDelete);186 let download;187 if (!gUseLegacySaver) {188 download = yield Downloads.createDownload({189 source: { url: httpUrl("source.txt"), isPrivate },190 target: getTempFile(TEST_TARGET_FILE_NAME).path,191 launchWhenSucceeded,192 launcherPath,193 });194 yield download.start();195 } else {196 download = yield promiseStartLegacyDownload(httpUrl("source.txt"), {197 isPrivate,198 launchWhenSucceeded,199 launcherPath: launchWhenSucceeded && launcherPath,200 });201 yield promiseDownloadStopped(download);202 }203 let isTemporary = launchWhenSucceeded && (autoDelete || isPrivate);204 let stat = yield OS.File.stat(download.target.path);205 if (Services.appinfo.OS == "WINNT") {206 // On Windows207 // Temporary downloads should be read-only208 do_check_eq(stat.winAttributes.readOnly, isTemporary ? true : false);209 } else {210 // On Linux, Mac211 // Temporary downloads should be read-only and not accessible to other212 // users, while permanently downloaded files should be readable and213 // writable as specified by the system umask.214 do_check_eq(stat.unixMode,215 isTemporary ? 0o400 : (0o666 & ~OS.Constants.Sys.umask));216 }217 }218 }219 }220 // Clean up the changes to the preference.221 Services.prefs.clearUserPref(kDeleteTempFileOnExit);222});223/**224 * Checks the referrer for downloads.225 */226add_task(function test_referrer()227{228 let sourcePath = "/test_referrer.txt";229 let sourceUrl = httpUrl("test_referrer.txt");230 let targetPath = getTempFile(TEST_TARGET_FILE_NAME).path;231 function cleanup() {232 gHttpServer.registerPathHandler(sourcePath, null);233 }234 do_register_cleanup(cleanup);235 gHttpServer.registerPathHandler(sourcePath, function (aRequest, aResponse) {236 aResponse.setHeader("Content-Type", "text/plain", false);237 do_check_true(aRequest.hasHeader("Referer"));238 do_check_eq(aRequest.getHeader("Referer"), TEST_REFERRER_URL);239 });240 let download = yield Downloads.createDownload({241 source: { url: sourceUrl, referrer: TEST_REFERRER_URL },242 target: targetPath,243 });244 do_check_eq(download.source.referrer, TEST_REFERRER_URL);245 yield download.start();246 download = yield Downloads.createDownload({247 source: { url: sourceUrl, referrer: TEST_REFERRER_URL,248 isPrivate: true },249 target: targetPath,250 });251 do_check_eq(download.source.referrer, TEST_REFERRER_URL);252 yield download.start();253 // Test the download still works for non-HTTP channel with referrer.254 sourceUrl = "data:text/html,<html><body></body></html>";255 download = yield Downloads.createDownload({256 source: { url: sourceUrl, referrer: TEST_REFERRER_URL },257 target: targetPath,258 });259 do_check_eq(download.source.referrer, TEST_REFERRER_URL);260 yield download.start();261 cleanup();262});263/**264 * Checks initial and final state and progress for a successful download.265 */266add_task(function test_initial_final_state()267{268 let download;269 if (!gUseLegacySaver) {270 // When testing DownloadCopySaver, we have control over the download, thus271 // we can check its state before it starts.272 download = yield promiseNewDownload();273 do_check_true(download.stopped);274 do_check_false(download.succeeded);275 do_check_false(download.canceled);276 do_check_true(download.error === null);277 do_check_eq(download.progress, 0);278 do_check_true(download.startTime === null);279 do_check_false(download.target.exists);280 do_check_eq(download.target.size, 0);281 yield download.start();282 } else {283 // When testing DownloadLegacySaver, the download is already started when it284 // is created, thus we cannot check its initial state.285 download = yield promiseStartLegacyDownload();286 yield promiseDownloadStopped(download);287 }288 do_check_true(download.stopped);289 do_check_true(download.succeeded);290 do_check_false(download.canceled);291 do_check_true(download.error === null);292 do_check_eq(download.progress, 100);293 do_check_true(isValidDate(download.startTime));294 do_check_true(download.target.exists);295 do_check_eq(download.target.size, TEST_DATA_SHORT.length);296});297/**298 * Checks the notification of the final download state.299 */300add_task(function test_final_state_notified()301{302 mustInterruptResponses();303 let download = yield promiseStartDownload(httpUrl("interruptible.txt"));304 let onchangeNotified = false;305 let lastNotifiedStopped;306 let lastNotifiedProgress;307 download.onchange = function () {308 onchangeNotified = true;309 lastNotifiedStopped = download.stopped;310 lastNotifiedProgress = download.progress;311 };312 // Allow the download to complete.313 let promiseAttempt = download.start();314 continueResponses();315 yield promiseAttempt;316 // The view should have been notified before the download completes.317 do_check_true(onchangeNotified);318 do_check_true(lastNotifiedStopped);319 do_check_eq(lastNotifiedProgress, 100);320});321/**322 * Checks intermediate progress for a successful download.323 */324add_task(function test_intermediate_progress()325{326 mustInterruptResponses();327 let download = yield promiseStartDownload(httpUrl("interruptible.txt"));328 yield promiseDownloadMidway(download);329 do_check_true(download.hasProgress);330 do_check_eq(download.currentBytes, TEST_DATA_SHORT.length);331 do_check_eq(download.totalBytes, TEST_DATA_SHORT.length * 2);332 // The final file size should not be computed for in-progress downloads.333 do_check_false(download.target.exists);334 do_check_eq(download.target.size, 0);335 // Continue after the first chunk of data is fully received.336 continueResponses();337 yield promiseDownloadStopped(download);338 do_check_true(download.stopped);339 do_check_eq(download.progress, 100);340 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT);341});342/**343 * Downloads a file with a "Content-Length" of 0 and checks the progress.344 */345add_task(function test_empty_progress()346{347 let download = yield promiseStartDownload(httpUrl("empty.txt"));348 yield promiseDownloadStopped(download);349 do_check_true(download.stopped);350 do_check_true(download.hasProgress);351 do_check_eq(download.progress, 100);352 do_check_eq(download.currentBytes, 0);353 do_check_eq(download.totalBytes, 0);354 // We should have received the content type even for an empty file.355 do_check_eq(download.contentType, "text/plain");356 do_check_eq((yield OS.File.stat(download.target.path)).size, 0);357 do_check_true(download.target.exists);358 do_check_eq(download.target.size, 0);359});360/**361 * Downloads a file with a "Content-Length" of 0 with the tryToKeepPartialData362 * property set, and ensures that the file is saved correctly.363 */364add_task(function test_empty_progress_tryToKeepPartialData()365{366 // Start a new download and configure it to keep partially downloaded data.367 let download;368 if (!gUseLegacySaver) {369 let targetFilePath = getTempFile(TEST_TARGET_FILE_NAME).path;370 download = yield Downloads.createDownload({371 source: httpUrl("empty.txt"),372 target: { path: targetFilePath,373 partFilePath: targetFilePath + ".part" },374 });375 download.tryToKeepPartialData = true;376 download.start();377 } else {378 // Start a download using nsIExternalHelperAppService, that is configured379 // to keep partially downloaded data by default.380 download = yield promiseStartExternalHelperAppServiceDownload(381 httpUrl("empty.txt"));382 }383 yield promiseDownloadStopped(download);384 // The target file should now have been created, and the ".part" file deleted.385 do_check_eq((yield OS.File.stat(download.target.path)).size, 0);386 do_check_true(download.target.exists);387 do_check_eq(download.target.size, 0);388 do_check_false(yield OS.File.exists(download.target.partFilePath));389 do_check_eq(32, download.saver.getSha256Hash().length);390});391/**392 * Downloads an empty file with no "Content-Length" and checks the progress.393 */394add_task(function test_empty_noprogress()395{396 let sourcePath = "/test_empty_noprogress.txt";397 let sourceUrl = httpUrl("test_empty_noprogress.txt");398 let deferRequestReceived = Promise.defer();399 // Register an interruptible handler that notifies us when the request occurs.400 function cleanup() {401 gHttpServer.registerPathHandler(sourcePath, null);402 }403 do_register_cleanup(cleanup);404 registerInterruptibleHandler(sourcePath,405 function firstPart(aRequest, aResponse) {406 aResponse.setHeader("Content-Type", "text/plain", false);407 deferRequestReceived.resolve();408 }, function secondPart(aRequest, aResponse) { });409 // Start the download, without allowing the request to finish.410 mustInterruptResponses();411 let download;412 if (!gUseLegacySaver) {413 // When testing DownloadCopySaver, we have control over the download, thus414 // we can hook its onchange callback that will be notified when the415 // download starts.416 download = yield promiseNewDownload(sourceUrl);417 download.onchange = function () {418 if (!download.stopped) {419 do_check_false(download.hasProgress);420 do_check_eq(download.currentBytes, 0);421 do_check_eq(download.totalBytes, 0);422 }423 };424 download.start();425 } else {426 // When testing DownloadLegacySaver, the download is already started when it427 // is created, and it may have already made all needed property change428 // notifications, thus there is no point in checking the onchange callback.429 download = yield promiseStartLegacyDownload(sourceUrl);430 }431 // Wait for the request to be received by the HTTP server, but don't allow the432 // request to finish yet. Before checking the download state, wait for the433 // events to be processed by the client.434 yield deferRequestReceived.promise;435 yield promiseExecuteSoon();436 // Check that this download has no progress report.437 do_check_false(download.stopped);438 do_check_false(download.hasProgress);439 do_check_eq(download.currentBytes, 0);440 do_check_eq(download.totalBytes, 0);441 // Now allow the response to finish.442 continueResponses();443 yield promiseDownloadStopped(download);444 // We should have received the content type even if no progress is reported.445 do_check_eq(download.contentType, "text/plain");446 // Verify the state of the completed download.447 do_check_true(download.stopped);448 do_check_false(download.hasProgress);449 do_check_eq(download.progress, 100);450 do_check_eq(download.currentBytes, 0);451 do_check_eq(download.totalBytes, 0);452 do_check_true(download.target.exists);453 do_check_eq(download.target.size, 0);454 do_check_eq((yield OS.File.stat(download.target.path)).size, 0);455});456/**457 * Calls the "start" method two times before the download is finished.458 */459add_task(function test_start_twice()460{461 mustInterruptResponses();462 let download;463 if (!gUseLegacySaver) {464 // When testing DownloadCopySaver, we have control over the download, thus465 // we can start the download later during the test.466 download = yield promiseNewDownload(httpUrl("interruptible.txt"));467 } else {468 // When testing DownloadLegacySaver, the download is already started when it469 // is created. Effectively, we are starting the download three times.470 download = yield promiseStartLegacyDownload(httpUrl("interruptible.txt"));471 }472 // Call the start method two times.473 let promiseAttempt1 = download.start();474 let promiseAttempt2 = download.start();475 // Allow the download to finish.476 continueResponses();477 // Both promises should now be resolved.478 yield promiseAttempt1;479 yield promiseAttempt2;480 do_check_true(download.stopped);481 do_check_true(download.succeeded);482 do_check_false(download.canceled);483 do_check_true(download.error === null);484 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT);485});486/**487 * Cancels a download and verifies that its state is reported correctly.488 */489add_task(function test_cancel_midway()490{491 mustInterruptResponses();492 // In this test case, we execute different checks that are only possible with493 // DownloadCopySaver or DownloadLegacySaver respectively.494 let download;495 let options = {};496 if (!gUseLegacySaver) {497 download = yield promiseNewDownload(httpUrl("interruptible.txt"));498 } else {499 download = yield promiseStartLegacyDownload(httpUrl("interruptible.txt"),500 options);501 }502 // Cancel the download after receiving the first part of the response.503 let deferCancel = Promise.defer();504 let onchange = function () {505 if (!download.stopped && !download.canceled && download.progress == 50) {506 // Cancel the download immediately during the notification.507 deferCancel.resolve(download.cancel());508 // The state change happens immediately after calling "cancel", but509 // temporary files or part files may still exist at this point.510 do_check_true(download.canceled);511 }512 };513 // Register for the notification, but also call the function directly in514 // case the download already reached the expected progress. This may happen515 // when using DownloadLegacySaver.516 download.onchange = onchange;517 onchange();518 let promiseAttempt;519 if (!gUseLegacySaver) {520 promiseAttempt = download.start();521 }522 // Wait on the promise returned by the "cancel" method to ensure that the523 // cancellation process finished and temporary files were removed.524 yield deferCancel.promise;525 if (gUseLegacySaver) {526 // The nsIWebBrowserPersist instance should have been canceled now.527 do_check_eq(options.outPersist.result, Cr.NS_ERROR_ABORT);528 }529 do_check_true(download.stopped);530 do_check_true(download.canceled);531 do_check_true(download.error === null);532 do_check_false(download.target.exists);533 do_check_eq(download.target.size, 0);534 do_check_false(yield OS.File.exists(download.target.path));535 // Progress properties are not reset by canceling.536 do_check_eq(download.progress, 50);537 do_check_eq(download.totalBytes, TEST_DATA_SHORT.length * 2);538 do_check_eq(download.currentBytes, TEST_DATA_SHORT.length);539 if (!gUseLegacySaver) {540 // The promise returned by "start" should have been rejected meanwhile.541 try {542 yield promiseAttempt;543 do_throw("The download should have been canceled.");544 } catch (ex if ex instanceof Downloads.Error) {545 do_check_false(ex.becauseSourceFailed);546 do_check_false(ex.becauseTargetFailed);547 }548 }549});550/**551 * Cancels a download while keeping partially downloaded data, and verifies that552 * both the target file and the ".part" file are deleted.553 */554add_task(function test_cancel_midway_tryToKeepPartialData()555{556 let download = yield promiseStartDownload_tryToKeepPartialData();557 do_check_true(yield OS.File.exists(download.target.path));558 do_check_true(yield OS.File.exists(download.target.partFilePath));559 yield download.cancel();560 yield download.removePartialData();561 do_check_true(download.stopped);562 do_check_true(download.canceled);563 do_check_true(download.error === null);564 do_check_false(yield OS.File.exists(download.target.path));565 do_check_false(yield OS.File.exists(download.target.partFilePath));566});567/**568 * Cancels a download right after starting it.569 */570add_task(function test_cancel_immediately()571{572 mustInterruptResponses();573 let download = yield promiseStartDownload(httpUrl("interruptible.txt"));574 let promiseAttempt = download.start();575 do_check_false(download.stopped);576 let promiseCancel = download.cancel();577 do_check_true(download.canceled);578 // At this point, we don't know whether the download has already stopped or579 // is still waiting for cancellation. We can wait on the promise returned580 // by the "start" method to know for sure.581 try {582 yield promiseAttempt;583 do_throw("The download should have been canceled.");584 } catch (ex if ex instanceof Downloads.Error) {585 do_check_false(ex.becauseSourceFailed);586 do_check_false(ex.becauseTargetFailed);587 }588 do_check_true(download.stopped);589 do_check_true(download.canceled);590 do_check_true(download.error === null);591 do_check_false(yield OS.File.exists(download.target.path));592 // Check that the promise returned by the "cancel" method has been resolved.593 yield promiseCancel;594});595/**596 * Cancels and restarts a download sequentially.597 */598add_task(function test_cancel_midway_restart()599{600 mustInterruptResponses();601 let download = yield promiseStartDownload(httpUrl("interruptible.txt"));602 // The first time, cancel the download midway.603 yield promiseDownloadMidway(download);604 yield download.cancel();605 do_check_true(download.stopped);606 // The second time, we'll provide the entire interruptible response.607 continueResponses();608 download.onchange = null;609 let promiseAttempt = download.start();610 // Download state should have already been reset.611 do_check_false(download.stopped);612 do_check_false(download.canceled);613 do_check_true(download.error === null);614 // For the following test, we rely on the network layer reporting its progress615 // asynchronously. Otherwise, there is nothing stopping the restarted616 // download from reaching the same progress as the first request already.617 do_check_eq(download.progress, 0);618 do_check_eq(download.totalBytes, 0);619 do_check_eq(download.currentBytes, 0);620 yield promiseAttempt;621 do_check_true(download.stopped);622 do_check_true(download.succeeded);623 do_check_false(download.canceled);624 do_check_true(download.error === null);625 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT);626});627/**628 * Cancels a download and restarts it from where it stopped.629 */630add_task(function test_cancel_midway_restart_tryToKeepPartialData()631{632 let download = yield promiseStartDownload_tryToKeepPartialData();633 yield download.cancel();634 do_check_true(download.stopped);635 do_check_true(download.hasPartialData);636 // The target file should not exist, but we should have kept the partial data.637 do_check_false(yield OS.File.exists(download.target.path));638 yield promiseVerifyContents(download.target.partFilePath, TEST_DATA_SHORT);639 do_check_false(download.target.exists);640 do_check_eq(download.target.size, 0);641 // Verify that the server sent the response from the start.642 do_check_eq(gMostRecentFirstBytePos, 0);643 // The second time, we'll request and obtain the second part of the response,644 // but we still stop when half of the remaining progress is reached.645 let deferMidway = Promise.defer();646 download.onchange = function () {647 if (!download.stopped && !download.canceled &&648 download.currentBytes == Math.floor(TEST_DATA_SHORT.length * 3 / 2)) {649 download.onchange = null;650 deferMidway.resolve();651 }652 };653 mustInterruptResponses();654 let promiseAttempt = download.start();655 // Continue when the number of bytes we received is correct, then check that656 // progress is at about 75 percent. The exact figure may vary because of657 // rounding issues, since the total number of bytes in the response might not658 // be a multiple of four.659 yield deferMidway.promise;660 do_check_true(download.progress > 72 && download.progress < 78);661 // Now we allow the download to finish.662 continueResponses();663 yield promiseAttempt;664 // Check that the server now sent the second part only.665 do_check_eq(gMostRecentFirstBytePos, TEST_DATA_SHORT.length);666 // The target file should now have been created, and the ".part" file deleted.667 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT);668 do_check_false(yield OS.File.exists(download.target.partFilePath));669});670/**671 * Cancels a download while keeping partially downloaded data, then removes the672 * data and restarts the download from the beginning.673 */674add_task(function test_cancel_midway_restart_removePartialData()675{676 let download = yield promiseStartDownload_tryToKeepPartialData();677 yield download.cancel();678 do_check_true(download.hasPartialData);679 yield promiseVerifyContents(download.target.partFilePath, TEST_DATA_SHORT);680 do_check_false(download.target.exists);681 do_check_eq(download.target.size, 0);682 yield download.removePartialData();683 do_check_false(download.hasPartialData);684 do_check_false(yield OS.File.exists(download.target.partFilePath));685 do_check_false(download.target.exists);686 do_check_eq(download.target.size, 0);687 // The second time, we'll request and obtain the entire response again.688 continueResponses();689 yield download.start();690 // Verify that the server sent the response from the start.691 do_check_eq(gMostRecentFirstBytePos, 0);692 // The target file should now have been created, and the ".part" file deleted.693 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT);694 do_check_false(yield OS.File.exists(download.target.partFilePath));695});696/**697 * Cancels a download while keeping partially downloaded data, then removes the698 * data and restarts the download from the beginning without keeping the partial699 * data anymore.700 */701add_task(function test_cancel_midway_restart_tryToKeepPartialData_false()702{703 let download = yield promiseStartDownload_tryToKeepPartialData();704 yield download.cancel();705 download.tryToKeepPartialData = false;706 // The above property change does not affect existing partial data.707 do_check_true(download.hasPartialData);708 yield promiseVerifyContents(download.target.partFilePath, TEST_DATA_SHORT);709 yield download.removePartialData();710 do_check_false(yield OS.File.exists(download.target.partFilePath));711 // Restart the download from the beginning.712 mustInterruptResponses();713 download.start();714 yield promiseDownloadMidway(download);715 yield promisePartFileReady(download);716 // While the download is in progress, we should still have a ".part" file.717 do_check_false(download.hasPartialData);718 do_check_true(yield OS.File.exists(download.target.partFilePath));719 // On Unix, verify that the file with the partially downloaded data is not720 // accessible by other users on the system.721 if (Services.appinfo.OS == "Darwin" || Services.appinfo.OS == "Linux") {722 do_check_eq((yield OS.File.stat(download.target.partFilePath)).unixMode,723 0o600);724 }725 yield download.cancel();726 // The ".part" file should be deleted now that the download is canceled.727 do_check_false(download.hasPartialData);728 do_check_false(yield OS.File.exists(download.target.partFilePath));729 // The third time, we'll request and obtain the entire response again.730 continueResponses();731 yield download.start();732 // Verify that the server sent the response from the start.733 do_check_eq(gMostRecentFirstBytePos, 0);734 // The target file should now have been created, and the ".part" file deleted.735 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT);736 do_check_false(yield OS.File.exists(download.target.partFilePath));737});738/**739 * Cancels a download right after starting it, then restarts it immediately.740 */741add_task(function test_cancel_immediately_restart_immediately()742{743 mustInterruptResponses();744 let download = yield promiseStartDownload(httpUrl("interruptible.txt"));745 let promiseAttempt = download.start();746 do_check_false(download.stopped);747 download.cancel();748 do_check_true(download.canceled);749 let promiseRestarted = download.start();750 do_check_false(download.stopped);751 do_check_false(download.canceled);752 do_check_true(download.error === null);753 // For the following test, we rely on the network layer reporting its progress754 // asynchronously. Otherwise, there is nothing stopping the restarted755 // download from reaching the same progress as the first request already.756 do_check_eq(download.hasProgress, false);757 do_check_eq(download.progress, 0);758 do_check_eq(download.totalBytes, 0);759 do_check_eq(download.currentBytes, 0);760 // Ensure the next request is now allowed to complete, regardless of whether761 // the canceled request was received by the server or not.762 continueResponses();763 try {764 yield promiseAttempt;765 // If we get here, it means that the first attempt actually succeeded. In766 // fact, this could be a valid outcome, because the cancellation request may767 // not have been processed in time before the download finished.768 do_print("The download should have been canceled.");769 } catch (ex if ex instanceof Downloads.Error) {770 do_check_false(ex.becauseSourceFailed);771 do_check_false(ex.becauseTargetFailed);772 }773 yield promiseRestarted;774 do_check_true(download.stopped);775 do_check_true(download.succeeded);776 do_check_false(download.canceled);777 do_check_true(download.error === null);778 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT);779});780/**781 * Cancels a download midway, then restarts it immediately.782 */783add_task(function test_cancel_midway_restart_immediately()784{785 mustInterruptResponses();786 let download = yield promiseStartDownload(httpUrl("interruptible.txt"));787 let promiseAttempt = download.start();788 // The first time, cancel the download midway.789 yield promiseDownloadMidway(download);790 download.cancel();791 do_check_true(download.canceled);792 let promiseRestarted = download.start();793 do_check_false(download.stopped);794 do_check_false(download.canceled);795 do_check_true(download.error === null);796 // For the following test, we rely on the network layer reporting its progress797 // asynchronously. Otherwise, there is nothing stopping the restarted798 // download from reaching the same progress as the first request already.799 do_check_eq(download.hasProgress, false);800 do_check_eq(download.progress, 0);801 do_check_eq(download.totalBytes, 0);802 do_check_eq(download.currentBytes, 0);803 // The second request is allowed to complete.804 continueResponses();805 try {806 yield promiseAttempt;807 do_throw("The download should have been canceled.");808 } catch (ex if ex instanceof Downloads.Error) {809 do_check_false(ex.becauseSourceFailed);810 do_check_false(ex.becauseTargetFailed);811 }812 yield promiseRestarted;813 do_check_true(download.stopped);814 do_check_true(download.succeeded);815 do_check_false(download.canceled);816 do_check_true(download.error === null);817 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT);818});819/**820 * Calls the "cancel" method on a successful download.821 */822add_task(function test_cancel_successful()823{824 let download = yield promiseStartDownload();825 yield promiseDownloadStopped(download);826 // The cancel method should succeed with no effect.827 yield download.cancel();828 do_check_true(download.stopped);829 do_check_true(download.succeeded);830 do_check_false(download.canceled);831 do_check_true(download.error === null);832 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT);833});834/**835 * Calls the "cancel" method two times in a row.836 */837add_task(function test_cancel_twice()838{839 mustInterruptResponses();840 let download = yield promiseStartDownload(httpUrl("interruptible.txt"));841 let promiseAttempt = download.start();842 do_check_false(download.stopped);843 let promiseCancel1 = download.cancel();844 do_check_true(download.canceled);845 let promiseCancel2 = download.cancel();846 try {847 yield promiseAttempt;848 do_throw("The download should have been canceled.");849 } catch (ex if ex instanceof Downloads.Error) {850 do_check_false(ex.becauseSourceFailed);851 do_check_false(ex.becauseTargetFailed);852 }853 // Both promises should now be resolved.854 yield promiseCancel1;855 yield promiseCancel2;856 do_check_true(download.stopped);857 do_check_false(download.succeeded);858 do_check_true(download.canceled);859 do_check_true(download.error === null);860 do_check_false(yield OS.File.exists(download.target.path));861});862/**863 * Checks the "refresh" method for succeeded downloads.864 */865add_task(function test_refresh_succeeded()866{867 let download = yield promiseStartDownload();868 yield promiseDownloadStopped(download);869 // The DownloadTarget properties should be the same after calling "refresh".870 yield download.refresh();871 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT);872 // If the file is removed, only the "exists" property should change, and the873 // "size" property should keep its previous value.874 yield OS.File.move(download.target.path, download.target.path + ".old");875 yield download.refresh();876 do_check_false(download.target.exists);877 do_check_eq(download.target.size, TEST_DATA_SHORT.length);878 // The DownloadTarget properties should be restored when the file is put back.879 yield OS.File.move(download.target.path + ".old", download.target.path);880 yield download.refresh();881 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT);882});883/**884 * Checks that a download cannot be restarted after the "finalize" method.885 */886add_task(function test_finalize()887{888 mustInterruptResponses();889 let download = yield promiseStartDownload(httpUrl("interruptible.txt"));890 let promiseFinalized = download.finalize();891 try {892 yield download.start();893 do_throw("It should not be possible to restart after finalization.");894 } catch (ex) { }895 yield promiseFinalized;896 do_check_true(download.stopped);897 do_check_false(download.succeeded);898 do_check_true(download.canceled);899 do_check_true(download.error === null);900 do_check_false(yield OS.File.exists(download.target.path));901});902/**903 * Checks that the "finalize" method can remove partially downloaded data.904 */905add_task(function test_finalize_tryToKeepPartialData()906{907 // Check finalization without removing partial data.908 let download = yield promiseStartDownload_tryToKeepPartialData();909 yield download.finalize();910 do_check_true(download.hasPartialData);911 do_check_true(yield OS.File.exists(download.target.partFilePath));912 // Clean up.913 yield download.removePartialData();914 // Check finalization while removing partial data.915 download = yield promiseStartDownload_tryToKeepPartialData();916 yield download.finalize(true);917 do_check_false(download.hasPartialData);918 do_check_false(yield OS.File.exists(download.target.partFilePath));919});920/**921 * Checks that whenSucceeded returns a promise that is resolved after a restart.922 */923add_task(function test_whenSucceeded_after_restart()924{925 mustInterruptResponses();926 let promiseSucceeded;927 let download;928 if (!gUseLegacySaver) {929 // When testing DownloadCopySaver, we have control over the download, thus930 // we can verify getting a reference before the first download attempt.931 download = yield promiseNewDownload(httpUrl("interruptible.txt"));932 promiseSucceeded = download.whenSucceeded();933 download.start();934 } else {935 // When testing DownloadLegacySaver, the download is already started when it936 // is created, thus we cannot get the reference before the first attempt.937 download = yield promiseStartLegacyDownload(httpUrl("interruptible.txt"));938 promiseSucceeded = download.whenSucceeded();939 }940 // Cancel the first download attempt.941 yield download.cancel();942 // The second request is allowed to complete.943 continueResponses();944 download.start();945 // Wait for the download to finish by waiting on the whenSucceeded promise.946 yield promiseSucceeded;947 do_check_true(download.stopped);948 do_check_true(download.succeeded);949 do_check_false(download.canceled);950 do_check_true(download.error === null);951 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT);952});953/**954 * Ensures download error details are reported on network failures.955 */956add_task(function test_error_source()957{958 let serverSocket = startFakeServer();959 try {960 let sourceUrl = "http://localhost:" + serverSocket.port + "/source.txt";961 let download;962 try {963 if (!gUseLegacySaver) {964 // When testing DownloadCopySaver, we want to check that the promise965 // returned by the "start" method is rejected.966 download = yield promiseNewDownload(sourceUrl);967 do_check_true(download.error === null);968 yield download.start();969 } else {970 // When testing DownloadLegacySaver, we cannot be sure whether we are971 // testing the promise returned by the "start" method or we are testing972 // the "error" property checked by promiseDownloadStopped. This happens973 // because we don't have control over when the download is started.974 download = yield promiseStartLegacyDownload(sourceUrl);975 yield promiseDownloadStopped(download);976 }977 do_throw("The download should have failed.");978 } catch (ex if ex instanceof Downloads.Error && ex.becauseSourceFailed) {979 // A specific error object is thrown when reading from the source fails.980 }981 // Check the properties now that the download stopped.982 do_check_true(download.stopped);983 do_check_false(download.canceled);984 do_check_true(download.error !== null);985 do_check_true(download.error.becauseSourceFailed);986 do_check_false(download.error.becauseTargetFailed);987 do_check_false(yield OS.File.exists(download.target.path));988 do_check_false(download.target.exists);989 do_check_eq(download.target.size, 0);990 } finally {991 serverSocket.close();992 }993});994/**995 * Ensures a download error is reported when receiving less bytes than what was996 * specified in the Content-Length header.997 */998add_task(function test_error_source_partial()999{1000 let sourceUrl = httpUrl("shorter-than-content-length-http-1-1.txt");1001 let enforcePref = Services.prefs.getBoolPref("network.http.enforce-framing.http1");1002 Services.prefs.setBoolPref("network.http.enforce-framing.http1", true);1003 function cleanup() {1004 Services.prefs.setBoolPref("network.http.enforce-framing.http1", enforcePref);1005 }1006 do_register_cleanup(cleanup);1007 let download;1008 try {1009 if (!gUseLegacySaver) {1010 // When testing DownloadCopySaver, we want to check that the promise1011 // returned by the "start" method is rejected.1012 download = yield promiseNewDownload(sourceUrl);1013 do_check_true(download.error === null);1014 yield download.start();1015 } else {1016 // When testing DownloadLegacySaver, we cannot be sure whether we are1017 // testing the promise returned by the "start" method or we are testing1018 // the "error" property checked by promiseDownloadStopped. This happens1019 // because we don't have control over when the download is started.1020 download = yield promiseStartLegacyDownload(sourceUrl);1021 yield promiseDownloadStopped(download);1022 }1023 do_throw("The download should have failed.");1024 } catch (ex if ex instanceof Downloads.Error && ex.becauseSourceFailed) {1025 // A specific error object is thrown when reading from the source fails.1026 }1027 // Check the properties now that the download stopped.1028 do_check_true(download.stopped);1029 do_check_false(download.canceled);1030 do_check_true(download.error !== null);1031 do_check_true(download.error.becauseSourceFailed);1032 do_check_false(download.error.becauseTargetFailed);1033 do_check_eq(download.error.result, Cr.NS_ERROR_NET_PARTIAL_TRANSFER);1034 do_check_false(yield OS.File.exists(download.target.path));1035 do_check_false(download.target.exists);1036 do_check_eq(download.target.size, 0);1037});1038/**1039 * Ensures download error details are reported on local writing failures.1040 */1041add_task(function test_error_target()1042{1043 // Create a file without write access permissions before downloading.1044 let targetFile = getTempFile(TEST_TARGET_FILE_NAME);1045 targetFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0);1046 try {1047 let download;1048 try {1049 if (!gUseLegacySaver) {1050 // When testing DownloadCopySaver, we want to check that the promise1051 // returned by the "start" method is rejected.1052 download = yield Downloads.createDownload({1053 source: httpUrl("source.txt"),1054 target: targetFile,1055 });1056 yield download.start();1057 } else {1058 // When testing DownloadLegacySaver, we cannot be sure whether we are1059 // testing the promise returned by the "start" method or we are testing1060 // the "error" property checked by promiseDownloadStopped. This happens1061 // because we don't have control over when the download is started.1062 download = yield promiseStartLegacyDownload(null,1063 { targetFile: targetFile });1064 yield promiseDownloadStopped(download);1065 }1066 do_throw("The download should have failed.");1067 } catch (ex if ex instanceof Downloads.Error && ex.becauseTargetFailed) {1068 // A specific error object is thrown when writing to the target fails.1069 }1070 // Check the properties now that the download stopped.1071 do_check_true(download.stopped);1072 do_check_false(download.canceled);1073 do_check_true(download.error !== null);1074 do_check_true(download.error.becauseTargetFailed);1075 do_check_false(download.error.becauseSourceFailed);1076 } finally {1077 // Restore the default permissions to allow deleting the file on Windows.1078 if (targetFile.exists()) {1079 targetFile.permissions = FileUtils.PERMS_FILE;1080 targetFile.remove(false);1081 }1082 }1083});1084/**1085 * Restarts a failed download.1086 */1087add_task(function test_error_restart()1088{1089 let download;1090 // Create a file without write access permissions before downloading.1091 let targetFile = getTempFile(TEST_TARGET_FILE_NAME);1092 targetFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0);1093 try {1094 // Use DownloadCopySaver or DownloadLegacySaver based on the test run,1095 // specifying the target file we created.1096 if (!gUseLegacySaver) {1097 download = yield Downloads.createDownload({1098 source: httpUrl("source.txt"),1099 target: targetFile,1100 });1101 download.start();1102 } else {1103 download = yield promiseStartLegacyDownload(null,1104 { targetFile: targetFile });1105 }1106 yield promiseDownloadStopped(download);1107 do_throw("The download should have failed.");1108 } catch (ex if ex instanceof Downloads.Error && ex.becauseTargetFailed) {1109 // A specific error object is thrown when writing to the target fails.1110 } finally {1111 // Restore the default permissions to allow deleting the file on Windows.1112 if (targetFile.exists()) {1113 targetFile.permissions = FileUtils.PERMS_FILE;1114 // Also for Windows, rename the file before deleting. This makes the1115 // current file name available immediately for a new file, while deleting1116 // in place prevents creation of a file with the same name for some time.1117 targetFile.moveTo(null, targetFile.leafName + ".delete.tmp");1118 targetFile.remove(false);1119 }1120 }1121 // Restart the download and wait for completion.1122 yield download.start();1123 do_check_true(download.stopped);1124 do_check_true(download.succeeded);1125 do_check_false(download.canceled);1126 do_check_true(download.error === null);1127 do_check_eq(download.progress, 100);1128 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT);1129});1130/**1131 * Executes download in both public and private modes.1132 */1133add_task(function test_public_and_private()1134{1135 let sourcePath = "/test_public_and_private.txt";1136 let sourceUrl = httpUrl("test_public_and_private.txt");1137 let testCount = 0;1138 // Apply pref to allow all cookies.1139 Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);1140 function cleanup() {1141 Services.prefs.clearUserPref("network.cookie.cookieBehavior");1142 Services.cookies.removeAll();1143 gHttpServer.registerPathHandler(sourcePath, null);1144 }1145 do_register_cleanup(cleanup);1146 gHttpServer.registerPathHandler(sourcePath, function (aRequest, aResponse) {1147 aResponse.setHeader("Content-Type", "text/plain", false);1148 if (testCount == 0) {1149 // No cookies should exist for first public download.1150 do_check_false(aRequest.hasHeader("Cookie"));1151 aResponse.setHeader("Set-Cookie", "foobar=1", false);1152 testCount++;1153 } else if (testCount == 1) {1154 // The cookie should exists for second public download.1155 do_check_true(aRequest.hasHeader("Cookie"));1156 do_check_eq(aRequest.getHeader("Cookie"), "foobar=1");1157 testCount++;1158 } else if (testCount == 2) {1159 // No cookies should exist for first private download.1160 do_check_false(aRequest.hasHeader("Cookie"));1161 }1162 });1163 let targetFile = getTempFile(TEST_TARGET_FILE_NAME);1164 yield Downloads.fetch(sourceUrl, targetFile);1165 yield Downloads.fetch(sourceUrl, targetFile);1166 if (!gUseLegacySaver) {1167 let download = yield Downloads.createDownload({1168 source: { url: sourceUrl, isPrivate: true },1169 target: targetFile,1170 });1171 yield download.start();1172 } else {1173 let download = yield promiseStartLegacyDownload(sourceUrl,1174 { isPrivate: true });1175 yield promiseDownloadStopped(download);1176 }1177 cleanup();1178});1179/**1180 * Checks the startTime gets updated even after a restart.1181 */1182add_task(function test_cancel_immediately_restart_and_check_startTime()1183{1184 let download = yield promiseStartDownload();1185 let startTime = download.startTime;1186 do_check_true(isValidDate(download.startTime));1187 yield download.cancel();1188 do_check_eq(download.startTime.getTime(), startTime.getTime());1189 // Wait for a timeout.1190 yield promiseTimeout(10);1191 yield download.start();1192 do_check_true(download.startTime.getTime() > startTime.getTime());1193});1194/**1195 * Executes download with content-encoding.1196 */1197add_task(function test_with_content_encoding()1198{1199 let sourcePath = "/test_with_content_encoding.txt";1200 let sourceUrl = httpUrl("test_with_content_encoding.txt");1201 function cleanup() {1202 gHttpServer.registerPathHandler(sourcePath, null);1203 }1204 do_register_cleanup(cleanup);1205 gHttpServer.registerPathHandler(sourcePath, function (aRequest, aResponse) {1206 aResponse.setHeader("Content-Type", "text/plain", false);1207 aResponse.setHeader("Content-Encoding", "gzip", false);1208 aResponse.setHeader("Content-Length",1209 "" + TEST_DATA_SHORT_GZIP_ENCODED.length, false);1210 let bos = new BinaryOutputStream(aResponse.bodyOutputStream);1211 bos.writeByteArray(TEST_DATA_SHORT_GZIP_ENCODED,1212 TEST_DATA_SHORT_GZIP_ENCODED.length);1213 });1214 let download = yield promiseStartDownload(sourceUrl);1215 yield promiseDownloadStopped(download);1216 do_check_eq(download.progress, 100);1217 do_check_eq(download.totalBytes, TEST_DATA_SHORT_GZIP_ENCODED.length);1218 // Ensure the content matches the decoded test data.1219 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT);1220 cleanup();1221});1222/**1223 * Checks that the file is not decoded if the extension matches the encoding.1224 */1225add_task(function test_with_content_encoding_ignore_extension()1226{1227 let sourcePath = "/test_with_content_encoding_ignore_extension.gz";1228 let sourceUrl = httpUrl("test_with_content_encoding_ignore_extension.gz");1229 function cleanup() {1230 gHttpServer.registerPathHandler(sourcePath, null);1231 }1232 do_register_cleanup(cleanup);1233 gHttpServer.registerPathHandler(sourcePath, function (aRequest, aResponse) {1234 aResponse.setHeader("Content-Type", "text/plain", false);1235 aResponse.setHeader("Content-Encoding", "gzip", false);1236 aResponse.setHeader("Content-Length",1237 "" + TEST_DATA_SHORT_GZIP_ENCODED.length, false);1238 let bos = new BinaryOutputStream(aResponse.bodyOutputStream);1239 bos.writeByteArray(TEST_DATA_SHORT_GZIP_ENCODED,1240 TEST_DATA_SHORT_GZIP_ENCODED.length);1241 });1242 let download = yield promiseStartDownload(sourceUrl);1243 yield promiseDownloadStopped(download);1244 do_check_eq(download.progress, 100);1245 do_check_eq(download.totalBytes, TEST_DATA_SHORT_GZIP_ENCODED.length);1246 do_check_eq(download.target.size, TEST_DATA_SHORT_GZIP_ENCODED.length);1247 // Ensure the content matches the encoded test data. We convert the data to a1248 // string before executing the content check.1249 yield promiseVerifyTarget(download.target,1250 String.fromCharCode.apply(String, TEST_DATA_SHORT_GZIP_ENCODED));1251 cleanup();1252});1253/**1254 * Cancels and restarts a download sequentially with content-encoding.1255 */1256add_task(function test_cancel_midway_restart_with_content_encoding()1257{1258 mustInterruptResponses();1259 let download = yield promiseStartDownload(httpUrl("interruptible_gzip.txt"));1260 // The first time, cancel the download midway.1261 let deferCancel = Promise.defer();1262 let onchange = function () {1263 if (!download.stopped && !download.canceled &&1264 download.currentBytes == TEST_DATA_SHORT_GZIP_ENCODED_FIRST.length) {1265 deferCancel.resolve(download.cancel());1266 }1267 };1268 // Register for the notification, but also call the function directly in1269 // case the download already reached the expected progress.1270 download.onchange = onchange;1271 onchange();1272 yield deferCancel.promise;1273 do_check_true(download.stopped);1274 // The second time, we'll provide the entire interruptible response.1275 continueResponses();1276 download.onchange = null;1277 yield download.start();1278 do_check_eq(download.progress, 100);1279 do_check_eq(download.totalBytes, TEST_DATA_SHORT_GZIP_ENCODED.length);1280 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT);1281});1282/**1283 * Download with parental controls enabled.1284 */1285add_task(function test_blocked_parental_controls()1286{1287 function cleanup() {1288 DownloadIntegration.shouldBlockInTest = false;1289 }1290 do_register_cleanup(cleanup);1291 DownloadIntegration.shouldBlockInTest = true;1292 let download;1293 try {1294 if (!gUseLegacySaver) {1295 // When testing DownloadCopySaver, we want to check that the promise1296 // returned by the "start" method is rejected.1297 download = yield promiseNewDownload();1298 yield download.start();1299 } else {1300 // When testing DownloadLegacySaver, we cannot be sure whether we are1301 // testing the promise returned by the "start" method or we are testing1302 // the "error" property checked by promiseDownloadStopped. This happens1303 // because we don't have control over when the download is started.1304 download = yield promiseStartLegacyDownload();1305 yield promiseDownloadStopped(download);1306 }1307 do_throw("The download should have blocked.");1308 } catch (ex if ex instanceof Downloads.Error && ex.becauseBlocked) {1309 do_check_true(ex.becauseBlockedByParentalControls);1310 do_check_true(download.error.becauseBlockedByParentalControls);1311 }1312 // Now that the download stopped, the target file should not exist.1313 do_check_false(yield OS.File.exists(download.target.path));1314 cleanup();1315});1316/**1317 * Test a download that will be blocked by Windows parental controls by1318 * resulting in an HTTP status code of 450.1319 */1320add_task(function test_blocked_parental_controls_httpstatus450()1321{1322 let download;1323 try {1324 if (!gUseLegacySaver) {1325 download = yield promiseNewDownload(httpUrl("parentalblocked.zip"));1326 yield download.start();1327 }1328 else {1329 download = yield promiseStartLegacyDownload(httpUrl("parentalblocked.zip"));1330 yield promiseDownloadStopped(download);1331 }1332 do_throw("The download should have blocked.");1333 } catch (ex if ex instanceof Downloads.Error && ex.becauseBlocked) {1334 do_check_true(ex.becauseBlockedByParentalControls);1335 do_check_true(download.error.becauseBlockedByParentalControls);1336 do_check_true(download.stopped);1337 }1338 do_check_false(yield OS.File.exists(download.target.path));1339});1340/**1341 * Check that DownloadCopySaver can always retrieve the hash.1342 * DownloadLegacySaver can only retrieve the hash when1343 * nsIExternalHelperAppService is invoked.1344 */1345add_task(function test_getSha256Hash()1346{1347 if (!gUseLegacySaver) {1348 let download = yield promiseStartDownload(httpUrl("source.txt"));1349 yield promiseDownloadStopped(download);1350 do_check_true(download.stopped);1351 do_check_eq(32, download.saver.getSha256Hash().length);1352 }1353});1354/**1355 * Create a download which will be reputation blocked.1356 *1357 * @param options1358 * {1359 * keepPartialData: bool,1360 * keepBlockedData: bool,1361 * }1362 * @return {Promise}1363 * @resolves The reputation blocked download.1364 * @rejects JavaScript exception.1365 */1366let promiseBlockedDownload = Task.async(function* (options) {1367 function cleanup() {1368 DownloadIntegration.shouldBlockInTestForApplicationReputation = false;1369 DownloadIntegration.shouldKeepBlockedDataInTest = false;1370 }1371 do_register_cleanup(cleanup);1372 let {keepPartialData, keepBlockedData} = options;1373 DownloadIntegration.shouldBlockInTestForApplicationReputation = true;1374 DownloadIntegration.shouldKeepBlockedDataInTest = keepBlockedData;1375 let download;1376 try {1377 if (keepPartialData) {1378 download = yield promiseStartDownload_tryToKeepPartialData();1379 continueResponses();1380 } else if (gUseLegacySaver) {1381 download = yield promiseStartLegacyDownload();1382 } else {1383 download = yield promiseNewDownload();1384 yield download.start();1385 do_throw("The download should have blocked.");1386 }1387 yield promiseDownloadStopped(download);1388 do_throw("The download should have blocked.");1389 } catch (ex if ex instanceof Downloads.Error && ex.becauseBlocked) {1390 do_check_true(ex.becauseBlockedByReputationCheck);1391 do_check_true(download.error.becauseBlockedByReputationCheck);1392 }1393 do_check_true(download.stopped);1394 do_check_false(download.succeeded);1395 do_check_false(yield OS.File.exists(download.target.path));1396 cleanup();1397 return download;1398});1399/**1400 * Checks that application reputation blocks the download and the target file1401 * does not exist.1402 */1403add_task(function test_blocked_applicationReputation()1404{1405 let download = yield promiseBlockedDownload({1406 keepPartialData: false,1407 keepBlockedData: false,1408 });1409 // Now that the download is blocked, the target file should not exist.1410 do_check_false(yield OS.File.exists(download.target.path));1411 do_check_false(download.target.exists);1412 do_check_eq(download.target.size, 0);1413 // There should also be no blocked data in this case1414 do_check_false(download.hasBlockedData);1415});1416/**1417 * Checks that application reputation blocks the download but maintains the1418 * blocked data, which will be deleted when the block is confirmed.1419 */1420add_task(function test_blocked_applicationReputation_confirmBlock()1421{1422 let download = yield promiseBlockedDownload({1423 keepPartialData: true,1424 keepBlockedData: true,1425 });1426 do_check_true(download.hasBlockedData);1427 do_check_true(yield OS.File.exists(download.target.partFilePath));1428 yield download.confirmBlock();1429 // After confirming the block the download should be in a failed state and1430 // have no downloaded data left on disk.1431 do_check_true(download.stopped);1432 do_check_false(download.succeeded);1433 do_check_false(download.hasBlockedData);1434 do_check_false(yield OS.File.exists(download.target.partFilePath));1435 do_check_false(yield OS.File.exists(download.target.path));1436 do_check_false(download.target.exists);1437 do_check_eq(download.target.size, 0);1438});1439/**1440 * Checks that application reputation blocks the download but maintains the1441 * blocked data, which will be used to complete the download when unblocking.1442 */1443add_task(function test_blocked_applicationReputation_unblock()1444{1445 let download = yield promiseBlockedDownload({1446 keepPartialData: true,1447 keepBlockedData: true,1448 });1449 do_check_true(download.hasBlockedData);1450 do_check_true(yield OS.File.exists(download.target.partFilePath));1451 yield download.unblock();1452 // After unblocking the download should have succeeded and be1453 // present at the final path.1454 do_check_true(download.stopped);1455 do_check_true(download.succeeded);1456 do_check_false(download.hasBlockedData);1457 do_check_false(yield OS.File.exists(download.target.partFilePath));1458 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT + TEST_DATA_SHORT);1459 // The only indication the download was previously blocked is the1460 // existence of the error, so we make sure it's still set.1461 do_check_true(download.error instanceof Downloads.Error);1462 do_check_true(download.error.becauseBlocked);1463 do_check_true(download.error.becauseBlockedByReputationCheck);1464});1465/**1466 * Check that calling cancel on a blocked download will not cause errors1467 */1468add_task(function test_blocked_applicationReputation_cancel()1469{1470 let download = yield promiseBlockedDownload({1471 keepPartialData: true,1472 keepBlockedData: true,1473 });1474 // This call should succeed on a blocked download.1475 yield download.cancel();1476 // Calling cancel should not have changed the current state, the download1477 // should still be blocked.1478 do_check_true(download.error.becauseBlockedByReputationCheck);1479 do_check_true(download.stopped);1480 do_check_false(download.succeeded);1481 do_check_true(download.hasBlockedData);1482});1483/**1484 * Checks that unblock and confirmBlock cannot race on a blocked download1485 */1486add_task(function test_blocked_applicationReputation_decisionRace()1487{1488 let download = yield promiseBlockedDownload({1489 keepPartialData: true,1490 keepBlockedData: true,1491 });1492 let unblockPromise = download.unblock();1493 let confirmBlockPromise = download.confirmBlock();1494 yield confirmBlockPromise.then(() => {1495 do_throw("confirmBlock should have failed.");1496 }, () => {});1497 yield unblockPromise;1498 // After unblocking the download should have succeeded and be1499 // present at the final path.1500 do_check_true(download.stopped);1501 do_check_true(download.succeeded);1502 do_check_false(download.hasBlockedData);1503 do_check_false(yield OS.File.exists(download.target.partFilePath));1504 do_check_true(yield OS.File.exists(download.target.path));1505 download = yield promiseBlockedDownload({1506 keepPartialData: true,1507 keepBlockedData: true,1508 });1509 confirmBlockPromise = download.confirmBlock();1510 unblockPromise = download.unblock();1511 yield unblockPromise.then(() => {1512 do_throw("unblock should have failed.");1513 }, () => {});1514 yield confirmBlockPromise;1515 // After confirming the block the download should be in a failed state and1516 // have no downloaded data left on disk.1517 do_check_true(download.stopped);1518 do_check_false(download.succeeded);1519 do_check_false(download.hasBlockedData);1520 do_check_false(yield OS.File.exists(download.target.partFilePath));1521 do_check_false(yield OS.File.exists(download.target.path));1522 do_check_false(download.target.exists);1523 do_check_eq(download.target.size, 0);1524});1525/**1526 * Checks that unblocking a blocked download fails if the blocked data has been1527 * removed.1528 */1529add_task(function test_blocked_applicationReputation_unblock()1530{1531 let download = yield promiseBlockedDownload({1532 keepPartialData: true,1533 keepBlockedData: true,1534 });1535 do_check_true(download.hasBlockedData);1536 do_check_true(yield OS.File.exists(download.target.partFilePath));1537 // Remove the blocked data without telling the download.1538 yield OS.File.remove(download.target.partFilePath);1539 let unblockPromise = download.unblock();1540 yield unblockPromise.then(() => {1541 do_throw("unblock should have failed.");1542 }, () => {});1543 // Even though unblocking failed the download state should have been updated1544 // to reflect the lack of blocked data.1545 do_check_false(download.hasBlockedData);1546 do_check_true(download.stopped);1547 do_check_false(download.succeeded);1548 do_check_false(download.target.exists);1549 do_check_eq(download.target.size, 0);1550});1551/**1552 * download.showContainingDirectory() action1553 */1554add_task(function test_showContainingDirectory() {1555 DownloadIntegration._deferTestShowDir = Promise.defer();1556 let targetPath = getTempFile(TEST_TARGET_FILE_NAME).path;1557 let download = yield Downloads.createDownload({1558 source: { url: httpUrl("source.txt") },1559 target: ""1560 });1561 try {1562 yield download.showContainingDirectory();1563 do_throw("Should have failed because of an invalid path.");1564 } catch (ex if ex instanceof Components.Exception) {1565 // Invalid paths on Windows are reported with NS_ERROR_FAILURE,1566 // but with NS_ERROR_FILE_UNRECOGNIZED_PATH on Mac/Linux1567 let validResult = ex.result == Cr.NS_ERROR_FILE_UNRECOGNIZED_PATH ||1568 ex.result == Cr.NS_ERROR_FAILURE;1569 do_check_true(validResult);1570 }1571 download = yield Downloads.createDownload({1572 source: { url: httpUrl("source.txt") },1573 target: targetPath1574 });1575 DownloadIntegration._deferTestShowDir = Promise.defer();1576 download.showContainingDirectory();1577 let result = yield DownloadIntegration._deferTestShowDir.promise;1578 do_check_eq(result, "success");1579});1580/**1581 * download.launch() action1582 */1583add_task(function test_launch() {1584 let customLauncher = getTempFile("app-launcher");1585 // Test both with and without setting a custom application.1586 for (let launcherPath of [null, customLauncher.path]) {1587 let download;1588 if (!gUseLegacySaver) {1589 // When testing DownloadCopySaver, we have control over the download, thus1590 // we can test that file is not launched if download.succeeded is not set.1591 download = yield Downloads.createDownload({1592 source: httpUrl("source.txt"),1593 target: getTempFile(TEST_TARGET_FILE_NAME).path,1594 launcherPath: launcherPath,1595 launchWhenSucceeded: true1596 });1597 try {1598 yield download.launch();1599 do_throw("Can't launch download file as it has not completed yet");1600 } catch (ex) {1601 do_check_eq(ex.message,1602 "launch can only be called if the download succeeded");1603 }1604 yield download.start();1605 } else {1606 // When testing DownloadLegacySaver, the download is already started when1607 // it is created, thus we don't test calling "launch" before starting.1608 download = yield promiseStartLegacyDownload(1609 httpUrl("source.txt"),1610 { launcherPath: launcherPath,1611 launchWhenSucceeded: true });1612 yield promiseDownloadStopped(download);1613 }1614 do_check_true(download.launchWhenSucceeded);1615 DownloadIntegration._deferTestOpenFile = Promise.defer();1616 download.launch();1617 let result = yield DownloadIntegration._deferTestOpenFile.promise;1618 // Verify that the results match the test case.1619 if (!launcherPath) {1620 // This indicates that the default handler has been chosen.1621 do_check_true(result === null);1622 } else {1623 // Check the nsIMIMEInfo instance that would have been used for launching.1624 do_check_eq(result.preferredAction, Ci.nsIMIMEInfo.useHelperApp);1625 do_check_true(result.preferredApplicationHandler1626 .QueryInterface(Ci.nsILocalHandlerApp)1627 .executable.equals(customLauncher));1628 }1629 }1630});1631/**1632 * Test passing an invalid path as the launcherPath property.1633 */1634add_task(function test_launcherPath_invalid() {1635 let download = yield Downloads.createDownload({1636 source: { url: httpUrl("source.txt") },1637 target: { path: getTempFile(TEST_TARGET_FILE_NAME).path },1638 launcherPath: " "1639 });1640 DownloadIntegration._deferTestOpenFile = Promise.defer();1641 yield download.start();1642 try {1643 download.launch();1644 result = yield DownloadIntegration._deferTestOpenFile.promise;1645 do_throw("Can't launch file with invalid custom launcher")1646 } catch (ex if ex instanceof Components.Exception) {1647 // Invalid paths on Windows are reported with NS_ERROR_FAILURE,1648 // but with NS_ERROR_FILE_UNRECOGNIZED_PATH on Mac/Linux1649 let validResult = ex.result == Cr.NS_ERROR_FILE_UNRECOGNIZED_PATH ||1650 ex.result == Cr.NS_ERROR_FAILURE;1651 do_check_true(validResult);1652 }1653});1654/**1655 * Tests that download.launch() is automatically called after1656 * the download finishes if download.launchWhenSucceeded = true1657 */1658add_task(function test_launchWhenSucceeded() {1659 let customLauncher = getTempFile("app-launcher");1660 // Test both with and without setting a custom application.1661 for (let launcherPath of [null, customLauncher.path]) {1662 DownloadIntegration._deferTestOpenFile = Promise.defer();1663 if (!gUseLegacySaver) {1664 let download = yield Downloads.createDownload({1665 source: httpUrl("source.txt"),1666 target: getTempFile(TEST_TARGET_FILE_NAME).path,1667 launchWhenSucceeded: true,1668 launcherPath: launcherPath,1669 });1670 yield download.start();1671 } else {1672 let download = yield promiseStartLegacyDownload(1673 httpUrl("source.txt"),1674 { launcherPath: launcherPath,1675 launchWhenSucceeded: true });1676 yield promiseDownloadStopped(download);1677 }1678 let result = yield DownloadIntegration._deferTestOpenFile.promise;1679 // Verify that the results match the test case.1680 if (!launcherPath) {1681 // This indicates that the default handler has been chosen.1682 do_check_true(result === null);1683 } else {1684 // Check the nsIMIMEInfo instance that would have been used for launching.1685 do_check_eq(result.preferredAction, Ci.nsIMIMEInfo.useHelperApp);1686 do_check_true(result.preferredApplicationHandler1687 .QueryInterface(Ci.nsILocalHandlerApp)1688 .executable.equals(customLauncher));1689 }1690 }1691});1692/**1693 * Tests that the proper content type is set for a normal download.1694 */1695add_task(function test_contentType() {1696 let download = yield promiseStartDownload(httpUrl("source.txt"));1697 yield promiseDownloadStopped(download);1698 do_check_eq("text/plain", download.contentType);1699});1700/**1701 * Tests that the serialization/deserialization of the startTime Date1702 * object works correctly.1703 */1704add_task(function test_toSerializable_startTime()1705{1706 let download1 = yield promiseStartDownload(httpUrl("source.txt"));1707 yield promiseDownloadStopped(download1);1708 let serializable = download1.toSerializable();1709 let reserialized = JSON.parse(JSON.stringify(serializable));1710 let download2 = yield Downloads.createDownload(reserialized);1711 do_check_eq(download1.startTime.constructor.name, "Date");1712 do_check_eq(download2.startTime.constructor.name, "Date");1713 do_check_eq(download1.startTime.toJSON(), download2.startTime.toJSON());1714});1715/**1716 * This test will call the platform specific operations within1717 * DownloadPlatform::DownloadDone. While there is no test to verify the1718 * specific behaviours, this at least ensures that there is no error or crash.1719 */1720add_task(function test_platform_integration()1721{1722 let downloadFiles = [];1723 let oldDeviceStorageEnabled = false;1724 try {1725 oldDeviceStorageEnabled = Services.prefs.getBoolPref("device.storage.enabled");1726 } catch (e) {1727 // This happens if the pref doesn't exist.1728 }1729 let downloadWatcherNotified = false;1730 let observer = {1731 observe: function(subject, topic, data) {1732 do_check_eq(topic, "download-watcher-notify");1733 do_check_eq(data, "modified");1734 downloadWatcherNotified = true;1735 }1736 }1737 Services.obs.addObserver(observer, "download-watcher-notify", false);1738 Services.prefs.setBoolPref("device.storage.enabled", true);1739 function cleanup() {1740 for (let file of downloadFiles) {1741 file.remove(true);1742 }1743 Services.obs.removeObserver(observer, "download-watcher-notify");1744 Services.prefs.setBoolPref("device.storage.enabled", oldDeviceStorageEnabled);1745 }1746 do_register_cleanup(cleanup);1747 for (let isPrivate of [false, true]) {1748 DownloadIntegration.downloadDoneCalled = false;1749 // Some platform specific operations only operate on files outside the1750 // temporary directory or in the Downloads directory (such as setting1751 // the Windows searchable attribute, and the Mac Downloads icon bouncing),1752 // so use the system Downloads directory for the target file.1753 let targetFilePath = yield DownloadIntegration.getSystemDownloadsDirectory();1754 targetFilePath = OS.Path.join(targetFilePath,1755 "test" + (Math.floor(Math.random() * 1000000)));1756 let targetFile = new FileUtils.File(targetFilePath);1757 downloadFiles.push(targetFile);1758 let download;1759 if (gUseLegacySaver) {1760 download = yield promiseStartLegacyDownload(httpUrl("source.txt"),1761 { targetFile: targetFile });1762 }1763 else {1764 download = yield Downloads.createDownload({1765 source: httpUrl("source.txt"),1766 target: targetFile,1767 });1768 download.start();1769 }1770 // Wait for the whenSucceeded promise to be resolved first.1771 // downloadDone should be called before the whenSucceeded promise is resolved.1772 yield download.whenSucceeded().then(function () {1773 do_check_true(DownloadIntegration.downloadDoneCalled);1774 do_check_true(downloadWatcherNotified);1775 });1776 // Then, wait for the promise returned by "start" to be resolved.1777 yield promiseDownloadStopped(download);1778 yield promiseVerifyTarget(download.target, TEST_DATA_SHORT);1779 }1780});1781/**1782 * Checks that downloads are added to browsing history when they start.1783 */1784add_task(function test_history()1785{1786 mustInterruptResponses();1787 // We will wait for the visit to be notified during the download.1788 yield PlacesTestUtils.clearHistory();1789 let promiseVisit = promiseWaitForVisit(httpUrl("interruptible.txt"));1790 // Start a download that is not allowed to finish yet.1791 let download = yield promiseStartDownload(httpUrl("interruptible.txt"));1792 // The history notifications should be received before the download completes.1793 let [time, transitionType] = yield promiseVisit;1794 do_check_eq(time, download.startTime.getTime() * 1000);1795 do_check_eq(transitionType, Ci.nsINavHistoryService.TRANSITION_DOWNLOAD);1796 // Restart and complete the download after clearing history.1797 yield PlacesTestUtils.clearHistory();1798 download.cancel();1799 continueResponses();1800 yield download.start();1801 // The restart should not have added a new history visit.1802 do_check_false(yield promiseIsURIVisited(httpUrl("interruptible.txt")));1803});1804/**1805 * Checks that downloads started by nsIHelperAppService are added to the1806 * browsing history when they start.1807 */1808add_task(function test_history_tryToKeepPartialData()1809{1810 // We will wait for the visit to be notified during the download.1811 yield PlacesTestUtils.clearHistory();1812 let promiseVisit =1813 promiseWaitForVisit(httpUrl("interruptible_resumable.txt"));1814 // Start a download that is not allowed to finish yet.1815 let beforeStartTimeMs = Date.now();1816 let download = yield promiseStartDownload_tryToKeepPartialData();1817 // The history notifications should be received before the download completes.1818 let [time, transitionType] = yield promiseVisit;1819 do_check_eq(transitionType, Ci.nsINavHistoryService.TRANSITION_DOWNLOAD);1820 // The time set by nsIHelperAppService may be different than the start time in1821 // the download object, thus we only check that it is a meaningful time. Note1822 // that we subtract one second from the earliest time to account for rounding.1823 do_check_true(time >= beforeStartTimeMs * 1000 - 1000000);1824 // Complete the download before finishing the test.1825 continueResponses();1826 yield promiseDownloadStopped(download);1827});1828/**1829 * Tests that the temp download files are removed on exit and exiting private1830 * mode after they have been launched.1831 */1832add_task(function test_launchWhenSucceeded_deleteTempFileOnExit() {1833 const kDeleteTempFileOnExit = "browser.helperApps.deleteTempFileOnExit";1834 let customLauncherPath = getTempFile("app-launcher").path;1835 let autoDeleteTargetPathOne = getTempFile(TEST_TARGET_FILE_NAME).path;1836 let autoDeleteTargetPathTwo = getTempFile(TEST_TARGET_FILE_NAME).path;1837 let noAutoDeleteTargetPath = getTempFile(TEST_TARGET_FILE_NAME).path;1838 let autoDeleteDownloadOne = yield Downloads.createDownload({1839 source: { url: httpUrl("source.txt"), isPrivate: true },1840 target: autoDeleteTargetPathOne,1841 launchWhenSucceeded: true,1842 launcherPath: customLauncherPath,1843 });1844 yield autoDeleteDownloadOne.start();1845 Services.prefs.setBoolPref(kDeleteTempFileOnExit, true);1846 let autoDeleteDownloadTwo = yield Downloads.createDownload({1847 source: httpUrl("source.txt"),1848 target: autoDeleteTargetPathTwo,1849 launchWhenSucceeded: true,1850 launcherPath: customLauncherPath,1851 });1852 yield autoDeleteDownloadTwo.start();1853 Services.prefs.setBoolPref(kDeleteTempFileOnExit, false);1854 let noAutoDeleteDownload = yield Downloads.createDownload({1855 source: httpUrl("source.txt"),1856 target: noAutoDeleteTargetPath,1857 launchWhenSucceeded: true,1858 launcherPath: customLauncherPath,1859 });1860 yield noAutoDeleteDownload.start();1861 Services.prefs.clearUserPref(kDeleteTempFileOnExit);1862 do_check_true(yield OS.File.exists(autoDeleteTargetPathOne));1863 do_check_true(yield OS.File.exists(autoDeleteTargetPathTwo));1864 do_check_true(yield OS.File.exists(noAutoDeleteTargetPath));1865 // Simulate leaving private browsing mode1866 Services.obs.notifyObservers(null, "last-pb-context-exited", null);1867 do_check_false(yield OS.File.exists(autoDeleteTargetPathOne));1868 // Simulate browser shutdown1869 let expire = Cc["@mozilla.org/uriloader/external-helper-app-service;1"]1870 .getService(Ci.nsIObserver);1871 expire.observe(null, "profile-before-change", null);1872 do_check_false(yield OS.File.exists(autoDeleteTargetPathTwo));1873 do_check_true(yield OS.File.exists(noAutoDeleteTargetPath));...
test_DownloadList.js
Source:test_DownloadList.js
1/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */2/* vim: set ts=2 et sw=2 tw=80: */3/* Any copyright is dedicated to the Public Domain.4 * http://creativecommons.org/publicdomain/zero/1.0/ */5/**6 * Tests the DownloadList object.7 */8"use strict";9////////////////////////////////////////////////////////////////////////////////10//// Globals11/**12 * Returns a PRTime in the past usable to add expirable visits.13 *14 * @note Expiration ignores any visit added in the last 7 days, but it's15 * better be safe against DST issues, by going back one day more.16 */17function getExpirablePRTime()18{19 let dateObj = new Date();20 // Normalize to midnight21 dateObj.setHours(0);22 dateObj.setMinutes(0);23 dateObj.setSeconds(0);24 dateObj.setMilliseconds(0);25 dateObj = new Date(dateObj.getTime() - 8 * 86400000);26 return dateObj.getTime() * 1000;27}28/**29 * Adds an expirable history visit for a download.30 *31 * @param aSourceUrl32 * String containing the URI for the download source, or null to use33 * httpUrl("source.txt").34 *35 * @return {Promise}36 * @rejects JavaScript exception.37 */38function promiseExpirableDownloadVisit(aSourceUrl)39{40 let deferred = Promise.defer();41 PlacesUtils.asyncHistory.updatePlaces(42 {43 uri: NetUtil.newURI(aSourceUrl || httpUrl("source.txt")),44 visits: [{45 transitionType: Ci.nsINavHistoryService.TRANSITION_DOWNLOAD,46 visitDate: getExpirablePRTime(),47 }]48 },49 {50 handleError: function handleError(aResultCode, aPlaceInfo) {51 let ex = new Components.Exception("Unexpected error in adding visits.",52 aResultCode);53 deferred.reject(ex);54 },55 handleResult: function () {},56 handleCompletion: function handleCompletion() {57 deferred.resolve();58 }59 });60 return deferred.promise;61}62////////////////////////////////////////////////////////////////////////////////63//// Tests64/**65 * Checks the testing mechanism used to build different download lists.66 */67add_task(function test_construction()68{69 let downloadListOne = yield promiseNewList();70 let downloadListTwo = yield promiseNewList();71 let privateDownloadListOne = yield promiseNewList(true);72 let privateDownloadListTwo = yield promiseNewList(true);73 do_check_neq(downloadListOne, downloadListTwo);74 do_check_neq(privateDownloadListOne, privateDownloadListTwo);75 do_check_neq(downloadListOne, privateDownloadListOne);76});77/**78 * Checks the methods to add and retrieve items from the list.79 */80add_task(function test_add_getAll()81{82 let list = yield promiseNewList();83 let downloadOne = yield promiseNewDownload();84 yield list.add(downloadOne);85 let itemsOne = yield list.getAll();86 do_check_eq(itemsOne.length, 1);87 do_check_eq(itemsOne[0], downloadOne);88 let downloadTwo = yield promiseNewDownload();89 yield list.add(downloadTwo);90 let itemsTwo = yield list.getAll();91 do_check_eq(itemsTwo.length, 2);92 do_check_eq(itemsTwo[0], downloadOne);93 do_check_eq(itemsTwo[1], downloadTwo);94 // The first snapshot should not have been modified.95 do_check_eq(itemsOne.length, 1);96});97/**98 * Checks the method to remove items from the list.99 */100add_task(function test_remove()101{102 let list = yield promiseNewList();103 yield list.add(yield promiseNewDownload());104 yield list.add(yield promiseNewDownload());105 let items = yield list.getAll();106 yield list.remove(items[0]);107 // Removing an item that was never added should not raise an error.108 yield list.remove(yield promiseNewDownload());109 items = yield list.getAll();110 do_check_eq(items.length, 1);111});112/**113 * Tests that the "add", "remove", and "getAll" methods on the global114 * DownloadCombinedList object combine the contents of the global DownloadList115 * objects for public and private downloads.116 */117add_task(function test_DownloadCombinedList_add_remove_getAll()118{119 let publicList = yield promiseNewList();120 let privateList = yield Downloads.getList(Downloads.PRIVATE);121 let combinedList = yield Downloads.getList(Downloads.ALL);122 let publicDownload = yield promiseNewDownload();123 let privateDownload = yield Downloads.createDownload({124 source: { url: httpUrl("source.txt"), isPrivate: true },125 target: getTempFile(TEST_TARGET_FILE_NAME).path,126 });127 yield publicList.add(publicDownload);128 yield privateList.add(privateDownload);129 do_check_eq((yield combinedList.getAll()).length, 2);130 yield combinedList.remove(publicDownload);131 yield combinedList.remove(privateDownload);132 do_check_eq((yield combinedList.getAll()).length, 0);133 yield combinedList.add(publicDownload);134 yield combinedList.add(privateDownload);135 do_check_eq((yield publicList.getAll()).length, 1);136 do_check_eq((yield privateList.getAll()).length, 1);137 do_check_eq((yield combinedList.getAll()).length, 2);138 yield publicList.remove(publicDownload);139 yield privateList.remove(privateDownload);140 do_check_eq((yield combinedList.getAll()).length, 0);141});142/**143 * Checks that views receive the download add and remove notifications, and that144 * adding and removing views works as expected, both for a normal and a combined145 * list.146 */147add_task(function test_notifications_add_remove()148{149 for (let isCombined of [false, true]) {150 // Force creating a new list for both the public and combined cases.151 let list = yield promiseNewList();152 if (isCombined) {153 list = yield Downloads.getList(Downloads.ALL);154 }155 let downloadOne = yield promiseNewDownload();156 let downloadTwo = yield Downloads.createDownload({157 source: { url: httpUrl("source.txt"), isPrivate: true },158 target: getTempFile(TEST_TARGET_FILE_NAME).path,159 });160 yield list.add(downloadOne);161 yield list.add(downloadTwo);162 // Check that we receive add notifications for existing elements.163 let addNotifications = 0;164 let viewOne = {165 onDownloadAdded: function (aDownload) {166 // The first download to be notified should be the first that was added.167 if (addNotifications == 0) {168 do_check_eq(aDownload, downloadOne);169 } else if (addNotifications == 1) {170 do_check_eq(aDownload, downloadTwo);171 }172 addNotifications++;173 },174 };175 yield list.addView(viewOne);176 do_check_eq(addNotifications, 2);177 // Check that we receive add notifications for new elements.178 yield list.add(yield promiseNewDownload());179 do_check_eq(addNotifications, 3);180 // Check that we receive remove notifications.181 let removeNotifications = 0;182 let viewTwo = {183 onDownloadRemoved: function (aDownload) {184 do_check_eq(aDownload, downloadOne);185 removeNotifications++;186 },187 };188 yield list.addView(viewTwo);189 yield list.remove(downloadOne);190 do_check_eq(removeNotifications, 1);191 // We should not receive remove notifications after the view is removed.192 yield list.removeView(viewTwo);193 yield list.remove(downloadTwo);194 do_check_eq(removeNotifications, 1);195 // We should not receive add notifications after the view is removed.196 yield list.removeView(viewOne);197 yield list.add(yield promiseNewDownload());198 do_check_eq(addNotifications, 3);199 }200});201/**202 * Checks that views receive the download change notifications, both for a203 * normal and a combined list.204 */205add_task(function test_notifications_change()206{207 for (let isCombined of [false, true]) {208 // Force creating a new list for both the public and combined cases.209 let list = yield promiseNewList();210 if (isCombined) {211 list = yield Downloads.getList(Downloads.ALL);212 }213 let downloadOne = yield promiseNewDownload();214 let downloadTwo = yield Downloads.createDownload({215 source: { url: httpUrl("source.txt"), isPrivate: true },216 target: getTempFile(TEST_TARGET_FILE_NAME).path,217 });218 yield list.add(downloadOne);219 yield list.add(downloadTwo);220 // Check that we receive change notifications.221 let receivedOnDownloadChanged = false;222 yield list.addView({223 onDownloadChanged: function (aDownload) {224 do_check_eq(aDownload, downloadOne);225 receivedOnDownloadChanged = true;226 },227 });228 yield downloadOne.start();229 do_check_true(receivedOnDownloadChanged);230 // We should not receive change notifications after a download is removed.231 receivedOnDownloadChanged = false;232 yield list.remove(downloadTwo);233 yield downloadTwo.start();234 do_check_false(receivedOnDownloadChanged);235 }236});237/**238 * Checks that the reference to "this" is correct in the view callbacks.239 */240add_task(function test_notifications_this()241{242 let list = yield promiseNewList();243 // Check that we receive change notifications.244 let receivedOnDownloadAdded = false;245 let receivedOnDownloadChanged = false;246 let receivedOnDownloadRemoved = false;247 let view = {248 onDownloadAdded: function () {249 do_check_eq(this, view);250 receivedOnDownloadAdded = true;251 },252 onDownloadChanged: function () {253 // Only do this check once.254 if (!receivedOnDownloadChanged) {255 do_check_eq(this, view);256 receivedOnDownloadChanged = true;257 }258 },259 onDownloadRemoved: function () {260 do_check_eq(this, view);261 receivedOnDownloadRemoved = true;262 },263 };264 yield list.addView(view);265 let download = yield promiseNewDownload();266 yield list.add(download);267 yield download.start();268 yield list.remove(download);269 // Verify that we executed the checks.270 do_check_true(receivedOnDownloadAdded);271 do_check_true(receivedOnDownloadChanged);272 do_check_true(receivedOnDownloadRemoved);273});274/**275 * Checks that download is removed on history expiration.276 */277add_task(function test_history_expiration()278{279 mustInterruptResponses();280 function cleanup() {281 Services.prefs.clearUserPref("places.history.expiration.max_pages");282 }283 do_register_cleanup(cleanup);284 // Set max pages to 0 to make the download expire.285 Services.prefs.setIntPref("places.history.expiration.max_pages", 0);286 let list = yield promiseNewList();287 let downloadOne = yield promiseNewDownload();288 let downloadTwo = yield promiseNewDownload(httpUrl("interruptible.txt"));289 let deferred = Promise.defer();290 let removeNotifications = 0;291 let downloadView = {292 onDownloadRemoved: function (aDownload) {293 if (++removeNotifications == 2) {294 deferred.resolve();295 }296 },297 };298 yield list.addView(downloadView);299 // Work with one finished download and one canceled download.300 yield downloadOne.start();301 downloadTwo.start();302 yield downloadTwo.cancel();303 // We must replace the visits added while executing the downloads with visits304 // that are older than 7 days, otherwise they will not be expired.305 yield PlacesTestUtils.clearHistory();306 yield promiseExpirableDownloadVisit();307 yield promiseExpirableDownloadVisit(httpUrl("interruptible.txt"));308 // After clearing history, we can add the downloads to be removed to the list.309 yield list.add(downloadOne);310 yield list.add(downloadTwo);311 // Force a history expiration.312 Cc["@mozilla.org/places/expiration;1"]313 .getService(Ci.nsIObserver).observe(null, "places-debug-start-expiration", -1);314 // Wait for both downloads to be removed.315 yield deferred.promise;316 cleanup();317});318/**319 * Checks all downloads are removed after clearing history.320 */321add_task(function test_history_clear()322{323 let list = yield promiseNewList();324 let downloadOne = yield promiseNewDownload();325 let downloadTwo = yield promiseNewDownload();326 yield list.add(downloadOne);327 yield list.add(downloadTwo);328 let deferred = Promise.defer();329 let removeNotifications = 0;330 let downloadView = {331 onDownloadRemoved: function (aDownload) {332 if (++removeNotifications == 2) {333 deferred.resolve();334 }335 },336 };337 yield list.addView(downloadView);338 yield downloadOne.start();339 yield downloadTwo.start();340 yield PlacesTestUtils.clearHistory();341 // Wait for the removal notifications that may still be pending.342 yield deferred.promise;343});344/**345 * Tests the removeFinished method to ensure that it only removes346 * finished downloads.347 */348add_task(function test_removeFinished()349{350 let list = yield promiseNewList();351 let downloadOne = yield promiseNewDownload();352 let downloadTwo = yield promiseNewDownload();353 let downloadThree = yield promiseNewDownload();354 let downloadFour = yield promiseNewDownload();355 yield list.add(downloadOne);356 yield list.add(downloadTwo);357 yield list.add(downloadThree);358 yield list.add(downloadFour);359 let deferred = Promise.defer();360 let removeNotifications = 0;361 let downloadView = {362 onDownloadRemoved: function (aDownload) {363 do_check_true(aDownload == downloadOne ||364 aDownload == downloadTwo ||365 aDownload == downloadThree);366 do_check_true(removeNotifications < 3);367 if (++removeNotifications == 3) {368 deferred.resolve();369 }370 },371 };372 yield list.addView(downloadView);373 // Start three of the downloads, but don't start downloadTwo, then set374 // downloadFour to have partial data. All downloads except downloadFour375 // should be removed.376 yield downloadOne.start();377 yield downloadThree.start();378 yield downloadFour.start();379 downloadFour.hasPartialData = true;380 list.removeFinished();381 yield deferred.promise;382 let downloads = yield list.getAll()383 do_check_eq(downloads.length, 1);384});385/**386 * Tests the global DownloadSummary objects for the public, private, and387 * combined download lists.388 */389add_task(function test_DownloadSummary()390{391 mustInterruptResponses();392 let publicList = yield promiseNewList();393 let privateList = yield Downloads.getList(Downloads.PRIVATE);394 let publicSummary = yield Downloads.getSummary(Downloads.PUBLIC);395 let privateSummary = yield Downloads.getSummary(Downloads.PRIVATE);396 let combinedSummary = yield Downloads.getSummary(Downloads.ALL);397 // Add a public download that has succeeded.398 let succeededPublicDownload = yield promiseNewDownload();399 yield succeededPublicDownload.start();400 yield publicList.add(succeededPublicDownload);401 // Add a public download that has been canceled midway.402 let canceledPublicDownload =403 yield promiseNewDownload(httpUrl("interruptible.txt"));404 canceledPublicDownload.start();405 yield promiseDownloadMidway(canceledPublicDownload);406 yield canceledPublicDownload.cancel();407 yield publicList.add(canceledPublicDownload);408 // Add a public download that is in progress.409 let inProgressPublicDownload =410 yield promiseNewDownload(httpUrl("interruptible.txt"));411 inProgressPublicDownload.start();412 yield promiseDownloadMidway(inProgressPublicDownload);413 yield publicList.add(inProgressPublicDownload);414 // Add a private download that is in progress.415 let inProgressPrivateDownload = yield Downloads.createDownload({416 source: { url: httpUrl("interruptible.txt"), isPrivate: true },417 target: getTempFile(TEST_TARGET_FILE_NAME).path,418 });419 inProgressPrivateDownload.start();420 yield promiseDownloadMidway(inProgressPrivateDownload);421 yield privateList.add(inProgressPrivateDownload);422 // Verify that the summary includes the total number of bytes and the423 // currently transferred bytes only for the downloads that are not stopped.424 // For simplicity, we assume that after a download is added to the list, its425 // current state is immediately propagated to the summary object, which is426 // true in the current implementation, though it is not guaranteed as all the427 // download operations may happen asynchronously.428 do_check_false(publicSummary.allHaveStopped);429 do_check_eq(publicSummary.progressTotalBytes, TEST_DATA_SHORT.length * 2);430 do_check_eq(publicSummary.progressCurrentBytes, TEST_DATA_SHORT.length);431 do_check_false(privateSummary.allHaveStopped);432 do_check_eq(privateSummary.progressTotalBytes, TEST_DATA_SHORT.length * 2);433 do_check_eq(privateSummary.progressCurrentBytes, TEST_DATA_SHORT.length);434 do_check_false(combinedSummary.allHaveStopped);435 do_check_eq(combinedSummary.progressTotalBytes, TEST_DATA_SHORT.length * 4);436 do_check_eq(combinedSummary.progressCurrentBytes, TEST_DATA_SHORT.length * 2);437 yield inProgressPublicDownload.cancel();438 // Stopping the download should have excluded it from the summary.439 do_check_true(publicSummary.allHaveStopped);440 do_check_eq(publicSummary.progressTotalBytes, 0);441 do_check_eq(publicSummary.progressCurrentBytes, 0);442 do_check_false(privateSummary.allHaveStopped);443 do_check_eq(privateSummary.progressTotalBytes, TEST_DATA_SHORT.length * 2);444 do_check_eq(privateSummary.progressCurrentBytes, TEST_DATA_SHORT.length);445 do_check_false(combinedSummary.allHaveStopped);446 do_check_eq(combinedSummary.progressTotalBytes, TEST_DATA_SHORT.length * 2);447 do_check_eq(combinedSummary.progressCurrentBytes, TEST_DATA_SHORT.length);448 yield inProgressPrivateDownload.cancel();449 // All the downloads should be stopped now.450 do_check_true(publicSummary.allHaveStopped);451 do_check_eq(publicSummary.progressTotalBytes, 0);452 do_check_eq(publicSummary.progressCurrentBytes, 0);453 do_check_true(privateSummary.allHaveStopped);454 do_check_eq(privateSummary.progressTotalBytes, 0);455 do_check_eq(privateSummary.progressCurrentBytes, 0);456 do_check_true(combinedSummary.allHaveStopped);457 do_check_eq(combinedSummary.progressTotalBytes, 0);458 do_check_eq(combinedSummary.progressCurrentBytes, 0);459});460/**461 * Checks that views receive the summary change notification. This is tested on462 * the combined summary when adding a public download, as we assume that if we463 * pass the test in this case we will also pass it in the others.464 */465add_task(function test_DownloadSummary_notifications()466{467 let list = yield promiseNewList();468 let summary = yield Downloads.getSummary(Downloads.ALL);469 let download = yield promiseNewDownload();470 yield list.add(download);471 // Check that we receive change notifications.472 let receivedOnSummaryChanged = false;473 yield summary.addView({474 onSummaryChanged: function () {475 receivedOnSummaryChanged = true;476 },477 });478 yield download.start();479 do_check_true(receivedOnSummaryChanged);480});481////////////////////////////////////////////////////////////////////////////////482//// Termination483let tailFile = do_get_file("tail.js");...
bg.js
Source:bg.js
...71 if (downloadLinks && downloadLinks.length !== 0) {72 downloadInterval = setInterval(() => {73 if (downloadLinks.length !== 0) {74 updateDownloadIds();75 download(downloadLinks.shift());76 } else {77 beginDownload();78 }79 }, 1000);80 } else {81 clearInterval(downloadInterval);82 chrome.storage.local.clear(() => lsManager.initStorage());83 }84 })85 .catch(err => {86 console.error(err);87 });88}89const onLoggedIn = (loginLink, callback) => {90 const baseLink = loginLink.match(/^(http)s?:\/\/.[^\/]*\//g)[0];91 if (windowIds[baseLink] && !visited[baseLink]) {92 chrome.tabs.query({93 windowId: windowIds[baseLink]94 }, (tabs) => {95 if (tabs.length == 0) {96 visiting[baseLink] = false;97 }98 });99 }100 if (!visited[baseLink] && visiting[baseLink]) {101 return;102 } else if (!visited[baseLink]) {103 visiting[baseLink] = true;104 chrome.windows.create({105 url: [loginLink],106 type: 'popup'107 }, (loginWindow) => {108 windowIds[baseLink] = loginWindow.id;109 function loginDownload(item) {110 chrome.downloads.cancel(item.id);111 visited[baseLink] = true;112 visiting[baseLink] = false;113 chrome.windows.remove(loginWindow.id);114 chrome.downloads.onCreated.removeListener(loginDownload);115 chrome.tabs.onUpdated.removeListener(granuleOpenedinBrowser);116 callback();117 // return true;118 }119 function granuleOpenedinBrowser(tabId, changeInfo, tab) {120 if (121 tabId == loginWindow.tabs[0].id &&122 tab.url == tab.title &&123 tab.url == loginLink124 ) {125 visited[baseLink] = true;126 chrome.windows.remove(loginWindow.id);127 chrome.tabs.onUpdated.removeListener(granuleOpenedinBrowser);128 chrome.downloads.onCreated.removeListener(loginDownload);129 callback();130 // return true;131 }132 }133 chrome.downloads.onCreated.addListener(loginDownload);134 chrome.tabs.onUpdated.addListener(granuleOpenedinBrowser);135 })136 // chrome.windows.create({137 // url: [loginLink]138 // }, (loginWindow)=>{139 // chrome.downloads.onCreated.addListener(function loginDownload(item){140 // chrome.downloads.cancel(141 // function(item){142 // console.log("deleting loginDownload");143 // });144 // chrome.windows.remove(loginWindow.id);145 // chrome.downloads.onCreated.removeListener(loginDownload);146 // visited[baseLink] = true;147 // callback();148 // });149 // })150 } else {151 callback();152 // return true;153 }154};155chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {156 request.message = request.message.toLowerCase();157 if (typeof(request) === "object") {158 if (request.message == "start-download") {159 downloadData.datasetName = request.datasetName;160 initDownload(request);161 } else if (request.message == "cancel-download") {162 // pauseAll();163 // if (confirm("Are you sure you want to cancel downloads?")) {164 // cancelAll();165 // } else {166 // resumeAll();167 // }168 cancelAll();169 } else if (request.message == "pause-download") {170 pauseAll();171 } else if (request.message == "resume-download") {172 resumeAll();173 } else if (request.message == "update-popup") {174 if (popupManager) {175 popupManager.postPogress();176 }177 } else if (request.message == "swal-fire") {178 closeSwal(sender);179 } else if (request.message == "update-granuleCount") {180 downloadData.totalNoofFiles = request.granuleCount;181 popupManager.updateGranuleCount(request.granuleCount);182 } else if (request.message == "download-completed") {183 reset(true);184 }185 }186});187function closeSwal(sender) {188 chrome.downloads.onCreated.addListener(function sendSwalMessage() {189 chrome.tabs.sendMessage(190 sender.tab.id, { message: "clear-swal-fire" },191 function(response) {192 if (response.message == "swal-closed") {193 chrome.downloads.onCreated.removeListener(sendSwalMessage);194 }195 });196 })197}198function download(downloadLink) {199 let filename = downloadLink.substring(downloadLink.lastIndexOf('/') + 1);200 let foldername = "Earthdata-BulkDownloads";201 chrome.storage.sync.get(['mainFolderName'], function(name) {202 if (name) {203 directoryName = name.mainFolderName;204 }205 });206 console.log(directoryName);207 const dataSetname = downloadData.datasetName;208 if (directoryName) {209 path = directoryName + '/' + dataSetname + "/" + filename;210 } else {211 path = foldername + '/' + dataSetname + "/" + filename;212 }213 console.log(path);214 console.log(foldername);215 chrome.downloads.download({216 url: downloadLink,217 filename: path218 }, function(downloadId) {219 if (cancelledJobs[jobId]) {220 chrome.downloads.cancel(downloadId);221 } else if (pausedJobs[jobId]) {222 modifyDownload(downloadId, pause);223 }224 downloadIds[downloadId] = downloadLink;225 });226}227function handleUndefined(variable, callback) {228 console.log(variable);229 if (variable === undefined || variable === "undefined") {...
FileDownload.js
Source:FileDownload.js
...146 {147 url = nexacro._toString(url); 148 url = nexacro._getImageLocation(url);149150 nexacro._download(url, this._hidden_frame_handle, initname, targetpath);151 ret = true;152 } 153 else if (downloadurl && downloadurl != undefined && downloadurl != "")154 {155 downloadurl = nexacro._getServiceLocation(downloadurl);156 nexacro._download(downloadurl, this._hidden_frame_handle, initname, targetpath);157 ret = true;158 }159 return ret;160 };161162 //===============================================================163 // nexacro.FileDownload : Events164 //===============================================================165 _pFileDownload.on_fire_onsuccess = function (url, targetfullpath)166 {167 var application = nexacro.getApplication();168 if (application)169 application._endCommProgress();170171 if (this.onsuccess && this.onsuccess._has_handlers && url != "")172 {173 var evt = new nexacro.FileDownloadEventInfo(this, "onsuccess", url, targetfullpath);174 return this.onsuccess._fireEvent(this, evt);175 }176 };177178 _pFileDownload.on_fire_onerror = function (obj, errortype, errormsg, errorobj, statuscode, requesturi, locationuri)179 {180 var application = nexacro.getApplication();181 if (application)182 application._endCommProgress();183184 if (this.onerror && this.onerror._has_handlers)185 {186 var evt = new nexacro.FileDownloadErrorEventInfo(obj, "onerror", errortype, errormsg, errorobj, statuscode, requesturi, locationuri);187 return this.onerror._fireEvent(this, evt);188 }189 };190191 _pFileDownload.on_load = function (status, data, url, errcode, httpcode, errmsg)192 {193 nexacro._onHttpSystemError(this, true, this, errcode, url, httpcode, url, null);194 if (status < 0)195 {196 var errormsg = nexacro._GetSystemErrorMsg(this, errcode);197 this.on_fire_onerror(this, "ObjectError", errormsg, this, 9901, null, null);198 }199 else200 {201 this.on_fire_onsuccess(url, data);202 }203 };204205 _pFileDownload.on_fire_onclick = function (button, alt_key, ctrl_key, shift_key, screenX, screenY, canvasX, canvasY, clientX, clientY, from_comp, from_refer_comp)206 {207 var ret = nexacro.Component.prototype.on_fire_onclick.call(this, button, alt_key, ctrl_key, shift_key, screenX, screenY, canvasX, canvasY, clientX, clientY, from_comp, from_refer_comp);208 this.download();209 return ret;210 };211212 _pFileDownload.on_fire_sys_onkeyup = function (key_code, alt_key, ctrl_key, shift_key, from_comp, from_refer_comp)213 {214 var ret = nexacro.Component.prototype.on_fire_sys_onkeyup.call(this, key_code, alt_key, ctrl_key, shift_key, from_comp, from_refer_comp);215 216 if (key_code == 13 || key_code == 32)217 {218 this.on_fire_onclick("none", false, false, false, -1, -1, -1, -1, -1, -1, this, this);219 }220221 return ret;222 };
...
language_options_dictionary_download_browsertest.js
Source:language_options_dictionary_download_browsertest.js
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4/**5 * TestFixture for testing messages of dictionary download progress in language6 * options WebUI.7 * @extends {testing.Test}8 * @constructor9 **/10function LanguagesOptionsDictionaryDownloadWebUITest() {}11LanguagesOptionsDictionaryDownloadWebUITest.prototype = {12 __proto__: testing.Test.prototype,13 /**14 * Browse to languages options.15 **/16 browsePreload: 'chrome://settings-frame/languages',17 /**18 * Register a mock dictionary handler.19 */20 preLoad: function() {21 this.makeAndRegisterMockHandler(['retryDictionaryDownload']);22 this.mockHandler.stubs().retryDictionaryDownload().23 will(callFunction(function() {24 options.LanguageOptions.onDictionaryDownloadBegin('en-US');25 }));26 },27};28// Verify that dictionary download success shows 'This language is used for29// spellchecking' message.30TEST_F('LanguagesOptionsDictionaryDownloadWebUITest',31 'testdictionaryDownloadSuccess',32 function() {33 options.LanguageOptions.onDictionaryDownloadSuccess('en-US');34 expectFalse($('language-options-spell-check-language-message').hidden);35 expectTrue($('language-options-dictionary-downloading-message').hidden);36 expectTrue($('language-options-dictionary-download-failed-message').hidden);37 expectTrue(38 $('language-options-dictionary-download-fail-help-message').hidden);39});40// Verify that dictionary download in progress shows 'Downloading spell check41// language' message.42TEST_F('LanguagesOptionsDictionaryDownloadWebUITest',43 'testdictionaryDownloadProgress',44 function() {45 options.LanguageOptions.onDictionaryDownloadBegin('en-US');46 expectTrue($('language-options-spell-check-language-message').hidden);47 expectFalse($('language-options-dictionary-downloading-message').hidden);48 expectTrue($('language-options-dictionary-download-failed-message').hidden);49 expectTrue(50 $('language-options-dictionary-download-fail-help-message').hidden);51});52// Verify that failure in dictionary download shows 'Dictionary download failed'53// message.54TEST_F('LanguagesOptionsDictionaryDownloadWebUITest',55 'testdictionaryDownloadFailed',56 function() {57 // Clear the failure counter:58 options.LanguageOptions.onDictionaryDownloadSuccess('en-US');59 // First failure shows a short error message.60 options.LanguageOptions.onDictionaryDownloadFailure('en-US');61 expectTrue($('language-options-spell-check-language-message').hidden);62 expectTrue($('language-options-dictionary-downloading-message').hidden);63 expectFalse($('language-options-dictionary-download-failed-message').hidden);64 expectTrue(65 $('language-options-dictionary-download-fail-help-message').hidden);66 // Second and all following failures show a longer error message.67 options.LanguageOptions.onDictionaryDownloadFailure('en-US');68 expectTrue($('language-options-spell-check-language-message').hidden);69 expectTrue($('language-options-dictionary-downloading-message').hidden);70 expectFalse($('language-options-dictionary-download-failed-message').hidden);71 expectFalse(72 $('language-options-dictionary-download-fail-help-message').hidden);73 options.LanguageOptions.onDictionaryDownloadFailure('en-US');74 expectTrue($('language-options-spell-check-language-message').hidden);75 expectTrue($('language-options-dictionary-downloading-message').hidden);76 expectFalse($('language-options-dictionary-download-failed-message').hidden);77 expectFalse(78 $('language-options-dictionary-download-fail-help-message').hidden);79});80// Verify that clicking the retry button calls the handler.81TEST_F('LanguagesOptionsDictionaryDownloadWebUITest',82 'testdictionaryDownloadRetry',83 function() {84 this.mockHandler.expects(once()).retryDictionaryDownload().85 will(callFunction(function() {86 options.LanguageOptions.onDictionaryDownloadBegin('en-US');87 }));88 options.LanguageOptions.onDictionaryDownloadFailure('en-US');89 $('dictionary-download-retry-button').click();...
Download.js
Source:Download.js
...16 ///////////////////////////////////17 ///////// Table Functions /////////18 ///////////////////////////////////19 downloadToTab(type, filename, options, active){20 this.download(type, filename, options, active, true);21 }22 ///////////////////////////////////23 ///////// Internal Logic //////////24 ///////////////////////////////////25 //trigger file download26 download(type, filename, options, range, interceptCallback){27 var downloadFunc = false;28 function buildLink(data, mime){29 if(interceptCallback){30 if(interceptCallback === true){31 this.triggerDownload(data, mime, type, filename, true);32 }else{33 interceptCallback(data);34 }35 }else{36 this.triggerDownload(data, mime, type, filename);37 }38 }39 if(typeof type == "function"){40 downloadFunc = type;41 }else{42 if(Download.downloaders[type]){43 downloadFunc = Download.downloaders[type];44 }else{45 console.warn("Download Error - No such download type found: ", type);46 }47 }48 if(downloadFunc){49 var list = this.generateExportList(range);50 downloadFunc.call(this.table, list , options || {}, buildLink.bind(this));51 }52 }53 generateExportList(range){54 var list = this.table.modules.export.generateExportList(this.table.options.downloadConfig, false, range || this.table.options.downloadRowRange, "download");55 //assign group header formatter56 var groupHeader = this.table.options.groupHeaderDownload;57 if(groupHeader && !Array.isArray(groupHeader)){58 groupHeader = [groupHeader];59 }60 list.forEach((row) => {61 var group;62 if(row.type === "group"){63 group = row.columns[0];64 if(groupHeader && groupHeader[row.indent]){65 group.value = groupHeader[row.indent](group.value, row.component._group.getRowCount(), row.component._group.getData(), row.component);66 }67 }68 });69 return list;70 }71 triggerDownload(data, mime, type, filename, newTab){72 var element = document.createElement('a'),73 blob = new Blob([data],{type:mime}),74 filename = filename || "Tabulator." + (typeof type === "function" ? "txt" : type);75 blob = this.table.options.downloadReady(data, blob);76 if(blob){77 if(newTab){78 window.open(window.URL.createObjectURL(blob));79 }else{80 if(navigator.msSaveOrOpenBlob){81 navigator.msSaveOrOpenBlob(blob, filename);82 }else{83 element.setAttribute('href', window.URL.createObjectURL(blob));84 //set file title85 element.setAttribute('download', filename);86 //trigger download87 element.style.display = 'none';88 document.body.appendChild(element);89 element.click();90 //remove temporary link element91 document.body.removeChild(element);92 }93 }94 this.dispatchExternal("downloadComplete");95 }96 }97 commsReceived(table, action, data){98 switch(action){99 case "intercept":100 this.download(data.type, "", data.options, data.active, data.intercept);101 break;102 }103 }104}105Download.moduleName = "download";106//load defaults107Download.downloaders = defaultDownloaders;...
data_card.js
Source:data_card.js
1/**send download summary data2*/3downloadSummaryData(){4 app.$data.working = true;5 this.data_downloading = true;6 app.sendMessage("download_summary_data", {});7},8/** take download summary data9 * @param messageData {json}10*/11takeDownloadSummaryData(messageData){12 var downloadLink = document.createElement("a");13 var blob = new Blob(["\ufeff", messageData.status.result]);14 var url = URL.createObjectURL(blob);15 downloadLink.href = url;16 downloadLink.download = "Exchange_Specialization_Summary_Data_Session_" + app.$data.session.id +".csv";17 document.body.appendChild(downloadLink);18 downloadLink.click();19 document.body.removeChild(downloadLink);20 this.data_downloading = false;21},22/**send download summary data23*/24downloadActionsData(){25 app.$data.working = true;26 this.data_downloading = true;27 app.sendMessage("download_action_data", {});28},29/** take download summary data30 * @param messageData {json}31*/32takeDownloadActionData(messageData){33 var downloadLink = document.createElement("a");34 var blob = new Blob(["\ufeff", messageData.status.result]);35 var url = URL.createObjectURL(blob);36 downloadLink.href = url;37 downloadLink.download = "Exchange_Specialization_Action_Data_Session_" + app.$data.session.id +".csv";38 document.body.appendChild(downloadLink);39 downloadLink.click();40 document.body.removeChild(downloadLink);41 this.data_downloading = false;42},43/**send download recruiter data44*/45downloadRecruiterData(){46 app.$data.working = true;47 this.data_downloading = true;48 app.sendMessage("download_recruiter_data", {});49},50/** take download recruiter data51 * @param messageData {json}52*/53takeDownloadRecruiterData(messageData){54 var downloadLink = document.createElement("a");55 var blob = new Blob(["\ufeff", messageData.status.result]);56 var url = URL.createObjectURL(blob);57 downloadLink.href = url;58 downloadLink.download = "Exchange_Specialization_Recruiter_Data_Session_" + app.$data.session.id +".csv";59 document.body.appendChild(downloadLink);60 downloadLink.click();61 document.body.removeChild(downloadLink);62 this.data_downloading = false;63},64/**send download payment data65*/66downloadPaymentData(){67 app.$data.working = true;68 this.data_downloading = true;69 app.sendMessage("download_payment_data", {});70},71/** take download payment data72 * @param messageData {json}73*/74takeDownloadPaymentData(messageData){75 var downloadLink = document.createElement("a");76 var blob = new Blob(["\ufeff", messageData.status.result]);77 var url = URL.createObjectURL(blob);78 downloadLink.href = url;79 downloadLink.download = "Exchange_Specialization_Payment_Data_Session_" + app.$data.session.id +".csv";80 document.body.appendChild(downloadLink);81 downloadLink.click();82 document.body.removeChild(downloadLink);83 this.data_downloading = false;...
模拟更新下载对话框.js
Source:模拟更新下载对话框.js
...14 })15 .show();16var downloadDialog = null;17var downloadId = -1;18function download(){19 downloadDialog = dialogs.build({20 title: "ä¸è½½ä¸...",21 positive: "æå",22 negative: "åæ¶",23 progress: {24 max: 100,25 showMinMax: true26 },27 autoDismiss: false28 })29 .on("positive", ()=>{30 if(downloadDialog.getActionButton("positive") == "æå"){31 stopDownload();32 downloadDialog.setActionButton("positive", "继ç»");...
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const context = await browser.newContext();5 const page = await context.newPage();6 const response = await page.route('**/*', route => route.fulfill({7 }));8 await page.screenshot({ path: `example.png` });9 await browser.close();10})();
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const context = await browser.newContext();5 const page = await context.newPage();6 await page.screenshot({ path: 'example.png' });7 await browser.close();8})();9const { download } = require('playwright');10const { download } = require('playwright');11const { download } = require('playwright');
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const context = await browser.newContext();5 const page = await context.newPage();6 await page.click('text=Playwright');7 await page.waitForTimeout(3000);8 await page.screenshot({ path: 'screenshot.png' });9 await browser.close();10})();11const { chromium } = require('playwright');12(async () => {13 const browser = await chromium.launch();14 const context = await browser.newContext();15 const page = await context.newPage();16 await page.click('text=Playwright');17 await page.waitForTimeout(3000);18 await page.screenshot({ path: 'screenshot.png' });19 await browser.close();20})();21const { chromium } = require('playwright');22(async () => {23 const browser = await chromium.launch();24 const context = await browser.newContext();25 const page = await context.newPage();26 await page.click('text=Playwright');27 await page.waitForTimeout(3000);28 await page.screenshot({ path: 'screenshot.png' });29 await browser.close();30})();31const { chromium } = require('playwright');32(async () => {33 const browser = await chromium.launch();34 const context = await browser.newContext();35 const page = await context.newPage();36 await page.click('text=Playwright');37 await page.waitForTimeout(3000);38 await page.screenshot({ path: 'screenshot.png' });39 await browser.close();40})();41const { chromium } = require('playwright');42(async () => {43 const browser = await chromium.launch();44 const context = await browser.newContext();45 const page = await context.newPage();
Using AI Code Generation
1const { chromium } = require('playwright');2const fs = require('fs');3(async () => {4 const browser = await chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 const buffer = await response.body();8 fs.writeFileSync('example.pdf', buffer);9 await browser.close();10})();11const { chromium } = require('playwright');12const fs = require('fs');13(async () => {14 const browser = await chromium.launch();15 const context = await browser.newContext();16 const page = await context.newPage();17 const buffer = await response.body();18 fs.writeFileSync('example.pdf', buffer);19 await browser.close();20})();21const { chromium } = require('playwright');22const fs = require('fs');23(async () => {24 const browser = await chromium.launch();25 const context = await browser.newContext();26 const page = await context.newPage();27 const buffer = await response.body();28 fs.writeFileSync('example.pdf', buffer);29 await browser.close();30})();31const { chromium } = require('playwright');32const fs = require('fs');33(async () => {34 const browser = await chromium.launch();35 const context = await browser.newContext();36 const page = await context.newPage();37 const buffer = await response.body();38 fs.writeFileSync('example.pdf', buffer);39 await browser.close();40})();41const { chromium } = require('playwright');42const fs = require('fs');43(async () => {44 const browser = await chromium.launch();45 const context = await browser.newContext();
Using AI Code Generation
1const { chromium } = require('playwright');2const fs = require('fs');3(async () => {4 const browser = await chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 const buffer = await response.body();8 fs.writeFile('google.html', buffer, (error) => {9 if (error) {10 console.log(error);11 }12 });13 await browser.close();14})();15const { chromium } = require('playwright');16const fs = require('fs');17(async () => {18 const browser = await chromium.launch();19 const context = await browser.newContext();20 const page = await context.newPage();21 const buffer = await response.body();22 fs.writeFile('google.html', buffer, (error) => {23 if (error) {24 console.log(error);25 }26 });27 await browser.close();28})();29const { chromium } = require('playwright');30const fs = require('fs');31(async () => {32 const browser = await chromium.launch();33 const context = await browser.newContext();34 const page = await context.newPage();35 const buffer = await response.body();36 fs.writeFile('google.html', buffer, (error) => {37 if (error) {38 console.log(error);39 }40 });41 await browser.close();42})();43const { chromium } = require('playwright');44const fs = require('fs');45(async () => {46 const browser = await chromium.launch();47 const context = await browser.newContext();48 const page = await context.newPage();49 const buffer = await response.body();50 fs.writeFile('google.html', buffer, (error) => {51 if (error) {52 console.log(error);53 }54 });55 await browser.close();56})();57const { chromium } = require('playwright
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const page = await browser.newPage();5 await page.screenshot({ path: 'google.png' });6 await browser.close();7})();8const { chromium } = require('playwright');9(async () => {10 const browser = await chromium.launch();11 const page = await browser.newPage();12 await page.screenshot({ path: 'google.png' });13 await browser.close();14})();15const { chromium } = require('playwright');16(async () => {17 const browser = await chromium.launch();18 const page = await browser.newPage();19 await page.screenshot({ path: 'google.png' });20 await browser.close();21})();22const { chromium } = require('playwright');23(async () => {24 const browser = await chromium.launch();25 const page = await browser.newPage();26 await page.screenshot({ path: 'google.png' });27 await browser.close();28})();
Using AI Code Generation
1const { download } = require("@playwright/test");2const path = require("path");3const fs = require("fs");4test("download file", async ({ page }) => {5 const downloadPath = path.join(__dirname, "downloads");6 const downloadArtifact = await download(page, downloadPath);7 const downloadedFile = path.join(downloadPath, downloadArtifact.suggestedFilename);8 expect(fs.existsSync(downloadedFile)).toBe(true);9});
Using AI Code Generation
1const download = require("playwright/lib/server/download");2const fs = require("fs");3const path = require("path");4const download = require("playwright/lib/server/download");5const fs = require("fs");6const path = require("path");7const download = require("playwright/lib/server/download");8const fs = require("fs");9const path = require("path");10const download = require("playwright/lib/server/download");11const fs = require("fs");12const path = require("path");13const download = require("playwright/lib/server/download");14const fs = require("fs");15const path = require("path");16const download = require("playwright/lib/server/download");17const fs = require("fs");18const path = require("path");19const download = require("playwright/lib/server/download");20const fs = require("fs");21const path = require("path");22const download = require("playwright/lib/server/download");23const fs = require("fs");24const path = require("path");25const download = require("playwright/lib/server/download");26const fs = require("fs");27const path = require("path");28const download = require("playwright/lib/server/download");29const fs = require("fs");30const path = require("path");31const download = require("playwright/lib/server/download");32const fs = require("fs");33const path = require("path");34const download = require("playwright/lib/server/download");35const fs = require("fs");36const path = require("path");37const download = require("playwright/lib/server/download");38const fs = require("fs");39const path = require("path");40const download = require("playwright/lib/server/download");41const fs = require("
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!