Skip to content

Commit

Permalink
Bug 1840810 - Preserve file content type when new name is unreadable …
Browse files Browse the repository at this point in the history
…or has no extension. r=dom-storage-reviewers,janv

Depends on D185428

Differential Revision: https://phabricator.services.mozilla.com/D185429
  • Loading branch information
jjjalkanen committed Aug 21, 2023
1 parent 4b11568 commit acad3ca
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 16 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 10 additions & 4 deletions dom/fs/parent/FileSystemContentTypeGuess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,24 @@

#include "FileSystemContentTypeGuess.h"

#include "ErrorList.h"
#include "mozilla/dom/QMResult.h"
#include "mozilla/dom/mime_guess_ffi_generated.h"
#include "mozilla/dom/quota/QuotaCommon.h"
#include "mozilla/dom/quota/ResultExtensions.h"
#include "nsString.h"

namespace mozilla::dom::fs {

ContentType FileSystemContentTypeGuess::FromPath(const Name& aPath) {
Result<ContentType, QMResult> FileSystemContentTypeGuess::FromPath(
const Name& aPath) {
NS_ConvertUTF16toUTF8 path(aPath);
ContentType contentType;
mimeGuessFromPath(&path, &contentType);
nsresult rv = mimeGuessFromPath(&path, &contentType);

if (contentType.IsEmpty()) {
return VoidCString();
// QM_TRY is too verbose.
if (NS_FAILED(rv)) {
return Err(QMResult(rv));
}

return contentType;
Expand Down
4 changes: 3 additions & 1 deletion dom/fs/parent/FileSystemContentTypeGuess.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
#ifndef DOM_FS_PARENT_FILESYSTEMCONTENTTYPEGUESS_H_
#define DOM_FS_PARENT_FILESYSTEMCONTENTTYPEGUESS_H_

#include "mozilla/Result.h"
#include "mozilla/dom/FileSystemTypes.h"
#include "mozilla/dom/quota/ForwardDecls.h"
#include "nsStringFwd.h"

namespace mozilla::dom::fs {

struct FileSystemContentTypeGuess {
static ContentType FromPath(const Name& aPath);
static Result<ContentType, QMResult> FromPath(const Name& aPath);
};

} // namespace mozilla::dom::fs
Expand Down
34 changes: 31 additions & 3 deletions dom/fs/parent/datamodel/FileSystemDatabaseManagerVersion001.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "FileSystemDatabaseManagerVersion001.h"

#include "ErrorList.h"
#include "FileSystemContentTypeGuess.h"
#include "FileSystemDataManager.h"
#include "FileSystemFileManager.h"
Expand All @@ -24,6 +25,7 @@
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/dom/quota/QuotaObject.h"
#include "mozilla/dom/quota/ResultExtensions.h"
#include "nsString.h"

namespace mozilla::dom {

Expand Down Expand Up @@ -663,7 +665,7 @@ Result<EntryId, QMResult> FileSystemDatabaseManagerVersion001::GetOrCreateFile(
QM_TRY_INSPECT(const EntryId& entryId, GetEntryId(aHandle));
MOZ_ASSERT(!entryId.IsEmpty());

const ContentType type = FileSystemContentTypeGuess::FromPath(name);
const ContentType type = DetermineContentType(name);

QM_TRY_UNWRAP(auto transaction, StartedTransaction::Create(mConnection));

Expand Down Expand Up @@ -929,7 +931,7 @@ Result<EntryId, QMResult> FileSystemDatabaseManagerVersion001::RenameEntry(
QM_TRY_UNWRAP(auto transaction, StartedTransaction::Create(mConnection));

if (isFile) {
const ContentType type = FileSystemContentTypeGuess::FromPath(aNewName);
const ContentType type = DetermineContentType(aNewName);
QM_TRY(
QM_TO_RESULT(PerformRenameFile(mConnection, aHandle, aNewName, type)));
} else {
Expand Down Expand Up @@ -996,7 +998,7 @@ Result<EntryId, QMResult> FileSystemDatabaseManagerVersion001::MoveEntry(
}

if (isFile) {
const ContentType type = FileSystemContentTypeGuess::FromPath(newName);
const ContentType type = DetermineContentType(newName);
QM_TRY(
QM_TO_RESULT(PerformRenameFile(mConnection, aHandle, newName, type)));
} else {
Expand Down Expand Up @@ -1535,6 +1537,32 @@ void TryRemoveDuringIdleMaintenance(
// Not implemented
}

ContentType DetermineContentType(const Name& aName) {
QM_TRY_UNWRAP(
auto typeResult,
QM_OR_ELSE_LOG_VERBOSE(
FileSystemContentTypeGuess::FromPath(aName),
([](const auto& aRv) -> Result<ContentType, QMResult> {
const nsresult rv = ToNSResult(aRv);
switch (rv) {
case NS_ERROR_FAILURE: /* There is an unknown new extension. */
return ContentType(""_ns); /* We clear the old extension. */

case NS_ERROR_INVALID_ARG: /* The name is garbled. */
[[fallthrough]];
case NS_ERROR_NOT_AVAILABLE: /* There is no extension. */
return VoidCString(); /* We keep the old extension. */

default:
MOZ_ASSERT_UNREACHABLE("Should never get here!");
return Err(aRv);
}
})),
ContentType(""_ns));

return typeResult;
}

} // namespace fs::data

} // namespace mozilla::dom
2 changes: 2 additions & 0 deletions dom/fs/parent/datamodel/FileSystemDatabaseManagerVersion001.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ nsresult GetFileAttributes(const FileSystemConnection& aConnection,

void TryRemoveDuringIdleMaintenance(const nsTArray<FileId>& aItemToRemove);

ContentType DetermineContentType(const Name& aName);

} // namespace data
} // namespace mozilla::dom::fs

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ Result<EntryId, QMResult> FileSystemDatabaseManagerVersion002::RenameEntry(
FileSystemChildMetadata newDesignation(parentId, aNewName);

if (isFile) {
const ContentType type = FileSystemContentTypeGuess::FromPath(aNewName);
const ContentType type = DetermineContentType(aNewName);
QM_TRY(
QM_TO_RESULT(RehashFile(mConnection, entryId, newDesignation, type)));
} else {
Expand Down Expand Up @@ -554,8 +554,7 @@ Result<EntryId, QMResult> FileSystemDatabaseManagerVersion002::MoveEntry(
aNewDesignation, isFile)));

if (isFile) {
const ContentType type =
FileSystemContentTypeGuess::FromPath(aNewDesignation.childName());
const ContentType type = DetermineContentType(aNewDesignation.childName());
QM_TRY(
QM_TO_RESULT(RehashFile(mConnection, entryId, aNewDesignation, type)));
} else {
Expand Down
1 change: 1 addition & 0 deletions dom/fs/parent/rust/mime-guess-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ authors = ["The Mozilla Project Developers"]

[dependencies]
mime_guess = "2.0.4"
nserror = { path = "../../../../../xpcom/rust/nserror" }
nsstring = { path = "../../../../../xpcom/rust/nsstring" }
17 changes: 13 additions & 4 deletions dom/fs/parent/rust/mime-guess-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,32 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate mime_guess;
extern crate nserror;
extern crate nsstring;

use nserror::{nsresult, NS_ERROR_FAILURE, NS_ERROR_INVALID_ARG, NS_ERROR_NOT_AVAILABLE, NS_OK};
use nsstring::{nsACString, nsCString};
use std::path::Path;
use std::str;

#[no_mangle]
pub extern "C" fn mimeGuessFromPath(path: &nsACString, content_type: &mut nsCString) {
pub extern "C" fn mimeGuessFromPath(path: &nsACString, content_type: &mut nsCString) -> nsresult {
let path_data = str::from_utf8(path.as_ref());
if path_data.is_err() {
return; // Not UTF8
return NS_ERROR_INVALID_ARG; // Not UTF8
}

let maybe_mime = mime_guess::from_path(Path::new(path_data.unwrap())).first_raw();
let content_path = Path::new(path_data.unwrap());
if content_path.extension().is_none() {
return NS_ERROR_NOT_AVAILABLE; // No mime type information
}

let maybe_mime = mime_guess::from_path(content_path).first_raw();
if maybe_mime.is_none() {
return; // Not recognized
return NS_ERROR_FAILURE; // Not recognized
}

content_type.assign(maybe_mime.unwrap());

NS_OK
}
2 changes: 1 addition & 1 deletion dom/fs/test/common/test_basics.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ exported_symbols.testContentTypeChangesOnFileMove = async function () {
const testParams = {
"testFile.json": "application/json",
testFile: oldType,
"testFile.äüö": oldType,
"testFile.äüö": "",
};

for (const [aName, aType] of Object.entries(testParams)) {
Expand Down

0 comments on commit acad3ca

Please sign in to comment.