michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsISupports.idl" michael@0: michael@0: interface nsIArray; michael@0: interface nsIBackgroundFileSaverObserver; michael@0: interface nsIFile; michael@0: michael@0: /** michael@0: * Allows saving data to a file, while handling all the input/output on a michael@0: * background thread, including the initial file name assignment and any michael@0: * subsequent renaming of the target file. michael@0: * michael@0: * This interface is designed for file downloads. Generally, they start in the michael@0: * temporary directory, while the user is selecting the final name. Then, they michael@0: * are moved to the chosen target directory with a ".part" extension appended to michael@0: * the file name. Finally, they are renamed when the download is completed. michael@0: * michael@0: * Components implementing both nsIBackgroundFileSaver and nsIStreamListener michael@0: * allow data to be fed using an implementation of OnDataAvailable that never michael@0: * blocks the calling thread. They suspend the request that drives the stream michael@0: * listener in case too much data is being fed, and resume it when the data has michael@0: * been written. Calling OnStopRequest does not necessarily close the target michael@0: * file, and the Finish method must be called to complete the operation. michael@0: * michael@0: * Components implementing both nsIBackgroundFileSaver and nsIAsyncOutputStream michael@0: * allow data to be fed directly to the non-blocking output stream, that however michael@0: * may return NS_BASE_STREAM_WOULD_BLOCK in case too much data is being fed. michael@0: * Closing the output stream does not necessarily close the target file, and the michael@0: * Finish method must be called to complete the operation. michael@0: * michael@0: * @remarks Implementations may require the consumer to always call Finish. If michael@0: * the object reference is released without calling Finish, a memory michael@0: * leak may occur, and the target file might be kept locked. All michael@0: * public methods of the interface may only be called from the main michael@0: * thread. michael@0: */ michael@0: [scriptable, uuid(c43544a4-682c-4262-b407-2453d26e660d)] michael@0: interface nsIBackgroundFileSaver : nsISupports michael@0: { michael@0: /** michael@0: * This observer receives notifications when the target file name changes and michael@0: * when the operation completes, successfully or not. michael@0: * michael@0: * @remarks A strong reference to the observer is held. Notification events michael@0: * are dispatched to the thread that created the object that michael@0: * implements nsIBackgroundFileSaver. michael@0: */ michael@0: attribute nsIBackgroundFileSaverObserver observer; michael@0: michael@0: /** michael@0: * An nsIArray of nsIX509CertList, representing a chain of X.509 signatures on michael@0: * the downloaded file. Each list may belong to a different signer and contain michael@0: * certificates all the way up to the root. michael@0: * michael@0: * @throws NS_ERROR_NOT_AVAILABLE michael@0: * In case this is called before the onSaveComplete method has been michael@0: * called to notify success, or enableSignatureInfo has not been michael@0: * called. michael@0: */ michael@0: readonly attribute nsIArray signatureInfo; michael@0: michael@0: /** michael@0: * The SHA-256 hash, in raw bytes, associated with the data that was saved. michael@0: * michael@0: * In case the enableAppend method has been called, the hash computation michael@0: * includes the contents of the existing file, if any. michael@0: * michael@0: * @throws NS_ERROR_NOT_AVAILABLE michael@0: * In case the enableSha256 method has not been called, or before the michael@0: * onSaveComplete method has been called to notify success. michael@0: */ michael@0: readonly attribute ACString sha256Hash; michael@0: michael@0: /** michael@0: * Instructs the component to compute the signatureInfo of the target file, michael@0: * and make it available in the signatureInfo property. michael@0: * michael@0: * @remarks This must be set on the main thread before the first call to michael@0: * setTarget. michael@0: */ michael@0: void enableSignatureInfo(); michael@0: michael@0: /** michael@0: * Instructs the component to compute the SHA-256 hash of the target file, and michael@0: * make it available in the sha256Hash property. michael@0: * michael@0: * @remarks This must be set on the main thread before the first call to michael@0: * setTarget. michael@0: */ michael@0: void enableSha256(); michael@0: michael@0: /** michael@0: * Instructs the component to append data to the initial target file, that michael@0: * will be specified by the first call to the setTarget method, instead of michael@0: * overwriting the file. michael@0: * michael@0: * If the initial target file does not exist, this method has no effect. michael@0: * michael@0: * @remarks This must be set on the main thread before the first call to michael@0: * setTarget. michael@0: */ michael@0: void enableAppend(); michael@0: michael@0: /** michael@0: * Sets the name of the output file to be written. The target can be changed michael@0: * after data has already been fed, in which case the existing file will be michael@0: * moved to the new destination. michael@0: * michael@0: * In case the specified file already exists, and this method is called for michael@0: * the first time, the file may be either overwritten or appended to, based on michael@0: * whether the enableAppend method was called. Subsequent calls always michael@0: * overwrite the specified target file with the previously saved data. michael@0: * michael@0: * No file will be written until this function is called at least once. It's michael@0: * recommended not to feed any data until the output file is set. michael@0: * michael@0: * If an input/output error occurs with the specified file, the save operation michael@0: * fails. Failure is notified asynchronously through the observer. michael@0: * michael@0: * @param aTarget michael@0: * New output file to be written. michael@0: * @param aKeepPartial michael@0: * Indicates whether aFile should be kept as partially completed, michael@0: * rather than deleted, if the operation fails or is canceled. This is michael@0: * generally set for downloads that use temporary ".part" files. michael@0: */ michael@0: void setTarget(in nsIFile aTarget, in bool aKeepPartial); michael@0: michael@0: /** michael@0: * Terminates access to the output file, then notifies the observer with the michael@0: * specified status code. A failure code will force the operation to be michael@0: * canceled, in which case the output file will be deleted if requested. michael@0: * michael@0: * This forces the involved streams to be closed, thus no more data should be michael@0: * fed to the component after this method has been called. michael@0: * michael@0: * This is the last method that should be called on this object, and the michael@0: * target file name cannot be changed anymore after this method has been michael@0: * called. Conversely, before calling this method, the file can still be michael@0: * renamed even if all the data has been fed. michael@0: * michael@0: * @param aStatus michael@0: * Result code that determines whether the operation should succeed or michael@0: * be canceled, and is notified to the observer. If the operation michael@0: * fails meanwhile for other reasons, or the observer has been already michael@0: * notified of completion, this status code is ignored. michael@0: */ michael@0: void finish(in nsresult aStatus); michael@0: }; michael@0: michael@0: [scriptable, uuid(ee7058c3-6e54-4411-b76b-3ce87b76fcb6)] michael@0: interface nsIBackgroundFileSaverObserver : nsISupports michael@0: { michael@0: /** michael@0: * Called when the name of the output file has been determined. This function michael@0: * may be called more than once if the target file is renamed while saving. michael@0: * michael@0: * @param aSaver michael@0: * Reference to the object that raised the notification. michael@0: * @param aTarget michael@0: * Name of the file that is being written. michael@0: */ michael@0: void onTargetChange(in nsIBackgroundFileSaver aSaver, in nsIFile aTarget); michael@0: michael@0: /** michael@0: * Called when the operation completed, and the target file has been closed. michael@0: * If the operation succeeded, the target file is ready to be used, otherwise michael@0: * it might have been already deleted. michael@0: * michael@0: * @param aSaver michael@0: * Reference to the object that raised the notification. michael@0: * @param aStatus michael@0: * Result code that determines whether the operation succeeded or michael@0: * failed, as well as the failure reason. michael@0: */ michael@0: void onSaveComplete(in nsIBackgroundFileSaver aSaver, in nsresult aStatus); michael@0: };