Bug 1424689 - Expose the File.type for File objects created via FileSystem API, r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D223396
This commit is contained in:
Andrea Marchesini 2024-10-01 06:25:30 +00:00
parent ee1f5ecbde
commit c08c22e705
4 changed files with 122 additions and 5 deletions

View file

@ -218,7 +218,28 @@ NS_IMETHODIMP
FileSystemTaskParentBase::Run() {
// This method can run in 2 different threads. Here why:
// 1. We are are on the I/O thread and we call IOWork().
// 2. After step 1, it returns back to the PBackground thread.
// 2. After step 1, if we need to run some code in the main-thread, we
// dispatch a runnable to this thread.
// 3. The final step happens in the PBackground thread.
// If we are here, it's because the I/O work has been done, but we have
// something to do on the main-thread.
if (NS_IsMainThread()) {
MOZ_ASSERT(MainThreadNeeded());
nsresult rv = MainThreadWork();
if (NS_WARN_IF(NS_FAILED(rv))) {
SetError(rv);
}
// Let's go back to PBackground thread to finish the work.
rv = mBackgroundEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
// Run I/O thread tasks
if (!mozilla::ipc::IsOnBackgroundThread()) {
@ -227,6 +248,14 @@ FileSystemTaskParentBase::Run() {
SetError(rv);
}
if (MainThreadNeeded()) {
rv = GetMainThreadSerialEventTarget()->Dispatch(this, NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
// Let's go back to PBackground thread to finish the work.
rv = mBackgroundEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {

View file

@ -53,9 +53,18 @@ class FileSystemParams;
* | | | | ---------> [IOWork] | |
* | | IPC | | | | |
* | | | | | | (5) | |
* | | | | -------------- | |
* | | | | | |_____________| |
* | | | | | |
* | | | | -------------* | |
* | | | | | |_____|_______| |
* | | | | | __________|_______ |
* | | | | | | | | |
* | | | | | | Main | | |
* | | | | | | Thread | | |
* | | | | | | V | |
* | | | | | | [MainThreadWork] | |
* | | IPC | | | (5.1) | | |
* | | | | | | | | |
* | | | | |<------------ | |
* | | | | | |__________________| |
* | | | | V |
* | | | | [HandleResult] |
* | | | | | |
@ -87,6 +96,7 @@ class FileSystemParams;
* during the operation, call [SetError] to record the error and then abort.
* (5) After finishing the task operation, call [HandleResult] to send the
* result back to the child process though the IPC.
* (5.1) Optional, we need to run some code in the main-thread.
* (6) Call [GetRequestResult] request result to prepare the parameters of the
* IPC. Because the formats of the error result for different task are the
* same, FileSystemTaskChildBase can handle the error message without
@ -199,6 +209,16 @@ class FileSystemTaskParentBase : public Runnable {
*/
virtual nsresult IOWork() = 0;
// In case `MainThreadNeeded()` returns true, the following method is called.
virtual nsresult MainThreadWork() {
MOZ_CRASH("This method should be implemented");
return NS_OK;
}
// If this returns true, after I/O work, we schedule a runnable to the
// main-thread before resolving the task on the PBackground one.
virtual bool MainThreadNeeded() const { return false; };
/*
* Wrap the task success result to FileSystemResponseValue for sending it
* through IPC. This method runs in the PBackground thread.

View file

@ -16,7 +16,9 @@
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/UnionTypes.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "nsCExternalHandlerService.h"
#include "nsIFile.h"
#include "nsIMIMEService.h"
#include "nsString.h"
namespace mozilla::dom {
@ -218,8 +220,18 @@ FileSystemResponseValue GetDirectoryListingTaskParent::GetSuccessRequestResult(
continue;
}
nsAutoString fileName;
path->GetLeafName(fileName);
int64_t fileSize = 0;
rv = path->GetFileSize(&fileSize);
if (NS_WARN_IF(NS_FAILED(rv))) {
continue;
}
FileSystemDirectoryListingResponseFile fileData;
RefPtr<BlobImpl> blobImpl = new FileBlobImpl(path);
RefPtr<BlobImpl> blobImpl = new FileBlobImpl(
fileName, mTargetData[i].mContentType, fileSize, path);
nsAutoString filePath;
filePath.Assign(mDOMPath);
@ -364,6 +376,55 @@ nsresult GetDirectoryListingTaskParent::IOWork() {
return NS_OK;
}
nsresult GetDirectoryListingTaskParent::MainThreadWork() {
MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
MOZ_ASSERT(NS_IsMainThread(), "Only call on main-thread!");
nsresult rv;
nsCOMPtr<nsIMIMEService> mimeService =
do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
for (unsigned i = 0; i < mTargetData.Length(); i++) {
if (mTargetData[i].mType != FileOrDirectoryPath::eFilePath) {
continue;
}
nsCOMPtr<nsIFile> file;
nsresult rv =
NS_NewLocalFile(mTargetData[i].mPath, true, getter_AddRefs(file));
if (NS_WARN_IF(NS_FAILED(rv))) {
continue;
}
nsAutoCString mimeType;
rv = mimeService->GetTypeFromFile(file, mimeType);
if (NS_FAILED(rv)) {
mimeType.Truncate();
}
AppendUTF8toUTF16(mimeType, mTargetData[i].mContentType);
}
return NS_OK;
}
bool GetDirectoryListingTaskParent::MainThreadNeeded() const {
MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
// We need to go to the main-thread only if we have files in the list of
// target.
for (const FileOrDirectoryPath& data : mTargetData) {
if (data.mType == FileOrDirectoryPath::eFilePath) {
return true;
}
}
return false;
}
nsresult GetDirectoryListingTaskParent::GetTargetPath(nsAString& aPath) const {
return mTargetPath->GetPath(aPath);
}

View file

@ -72,6 +72,10 @@ class GetDirectoryListingTaskParent final : public FileSystemTaskParentBase {
virtual nsresult IOWork() override;
virtual nsresult MainThreadWork() override;
virtual bool MainThreadNeeded() const override;
nsCOMPtr<nsIFile> mTargetPath;
nsString mDOMPath;
nsString mFilters;
@ -79,6 +83,9 @@ class GetDirectoryListingTaskParent final : public FileSystemTaskParentBase {
struct FileOrDirectoryPath {
nsString mPath;
// Set on the main-thread
nsString mContentType;
enum { eFilePath, eDirectoryPath } mType;
};