Commit abf127a4 authored by Trent Apted's avatar Trent Apted Committed by Commit Bot

Use a generic approach to support non-native file handles on ChromeOS WebUI

Currently, when opening files from the ChromeOS file manager, users see
an error trying if the file is from an MTP device or an ARC++ "document
provider" mount under the media virtual folder (e.g. "Pictures").
See https://crbug.com/895479 for details about document provider.

An approach added in r778183 was to check for a "/provided" path prefix,
but this only works for some non-native filesystem types on ChromeOS.
Generalise it by asking storage::ExternalMountPoints to lookup the
"virtual" path, which contains the path components necessary to extract
the filesystem type.

Use remains restricted to chrome:// WebUIs on ChromeOS.

The code is still covered by tests added in r778183 (i.e.
SystemWebAppManagerLaunchDirectoryFileSystemProviderBrowserTest.*).
https://crbug.com/1102287 tracks making testing of android volumes
possible outside of the files app.

Bug: 1099474
Change-Id: I37a0239dec4d9b7c6bba866302db00b5d84941b3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2279413Reviewed-by: default avatarMarijn Kruisselbrink <mek@chromium.org>
Commit-Queue: Trent Apted <tapted@chromium.org>
Cr-Commit-Position: refs/heads/master@{#786161}
parent 7343f5b1
......@@ -442,8 +442,8 @@ void NativeFileSystemFileWriterImpl::ComputeHashForSwapFile(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
#if defined(OS_CHROMEOS)
// TOOD(crbug.com/1103076): Extend this check to non-native paths.
DCHECK(swap_url().type() == storage::kFileSystemTypeNativeLocal ||
swap_url().type() == storage::kFileSystemTypeProvided ||
swap_url().type() == storage::kFileSystemTypeNativeForPlatformApp)
<< swap_url().type();
#else
......
......@@ -99,20 +99,20 @@ class CONTENT_EXPORT NativeFileSystemFileWriterImpl
void DidAnnotateFile(CloseCallback callback,
quarantine::mojom::QuarantineFileResult result);
// After write checks apply to native local paths, file system provider paths,
// and platform app native paths.
// After write checks should apply to paths on all filesystems except
// temporary file systems.
// TOOD(crbug.com/1103076): Extend this check to non-native paths.
bool RequireAfterWriteCheck() const {
return url().type() == storage::kFileSystemTypeNativeLocal ||
url().type() == storage::kFileSystemTypeProvided ||
url().type() == storage::kFileSystemTypeNativeForPlatformApp;
}
// Quarantine checks apply to native local paths, file system provider paths,
// and platform app native paths.
// Quarantine checks should apply to paths on all filesystems except
// temporary file systems.
// TOOD(crbug.com/1103076): Extend this check to non-native paths.
bool CanSkipQuarantineCheck() const {
bool need_quarantine_check =
url().type() == storage::kFileSystemTypeNativeLocal ||
url().type() == storage::kFileSystemTypeProvided ||
url().type() == storage::kFileSystemTypeNativeForPlatformApp;
return skip_quarantine_check_for_testing_ || !need_quarantine_check;
......
......@@ -9,6 +9,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/back_forward_cache.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/common/url_utils.h"
#include "storage/common/file_system/file_system_types.h"
namespace content {
......@@ -27,22 +28,20 @@ NativeFileSystemHandleBase::NativeFileSystemHandleBase(
handle_state_.file_system.is_valid())
<< url_.mount_type();
// We support sandboxed file system and native file systems on all platforms.
DCHECK(url_.type() == storage::kFileSystemTypeNativeLocal ||
url_.type() == storage::kFileSystemTypeTemporary ||
bool chromeos_webui = false;
#if defined(OS_CHROMEOS)
// On Chrome OS, we additionally support File System Provider API, and
// file systems available to platform Apps.
url_.type() == storage::kFileSystemTypeNativeForPlatformApp ||
url_.type() == storage::kFileSystemTypeProvided ||
// WebUIs on ChromeOS support a range of file system types.
chromeos_webui = HasWebUIScheme(context_.origin.GetURL());
#endif
// We support sandboxed file system and native file systems on all platforms.
DCHECK(chromeos_webui || url_.type() == storage::kFileSystemTypeNativeLocal ||
url_.type() == storage::kFileSystemTypeTemporary ||
url_.type() == storage::kFileSystemTypeTest)
<< url_.type();
if (ShouldTrackUsage()) {
DCHECK(url_.type() == storage::kFileSystemTypeNativeLocal ||
url_.type() == storage::kFileSystemTypeNativeForPlatformApp ||
url_.type() == storage::kFileSystemTypeProvided)
DCHECK(chromeos_webui || url_.type() == storage::kFileSystemTypeNativeLocal)
<< url.type();
DCHECK_EQ(url_.mount_type(), storage::kFileSystemTypeIsolated);
......
......@@ -28,6 +28,7 @@
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "net/base/escape.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "storage/browser/file_system/external_mount_points.h"
#include "storage/browser/file_system/file_system_context.h"
#include "storage/browser/file_system/file_system_operation_runner.h"
#include "storage/browser/file_system/file_system_url.h"
......@@ -49,11 +50,30 @@ using HandleType = NativeFileSystemPermissionContext::HandleType;
namespace {
#if defined(OS_CHROMEOS)
// Path prefix for Chrome OS File System Provider (FSP) file systems. Copied
// here to avoid complex dependencies. See |kProvidedMountPointRoot| in
// chrome/browser/chromeos/file_system_provider/mount_path_util.cc.
// Files and directories provided by FSP API resides in this directory.
static constexpr char kProvidedMountPointRoot[] = "/provided";
storage::FileSystemType GetFileSystemTypeForCrackedPath(
const base::FilePath& cracked_path,
std::string* filesystem_id) {
// There is also an instance of ExternalMountPoints sitting in
// NativeFileSystemManagerImpl::context(), but ChromeOS registers its volumes
// in the system instance.
auto* external_mount_points =
storage::ExternalMountPoints::GetSystemInstance();
base::FilePath virtual_path;
if (!external_mount_points->GetVirtualPath(cracked_path, &virtual_path)) {
return storage::kFileSystemTypeUnknown;
}
storage::FileSystemType type;
storage::FileSystemMountOption mount_option;
std::string cracked_id;
base::FilePath path;
if (external_mount_points->CrackVirtualPath(virtual_path, filesystem_id,
&type, &cracked_id, &path,
&mount_option)) {
return type;
}
return storage::kFileSystemTypeUnknown;
}
#endif // OS_CHROMEOS
void ShowFilePickerOnUIThread(const url::Origin& requesting_origin,
......@@ -354,16 +374,13 @@ void NativeFileSystemManagerImpl::DidResolveForSerializeHandle(
break;
}
default:
#if defined(OS_CHROMEOS)
// For now, we don't support serializing handles for Chrome OS specific
// types, run |callback| with an empty vector to indicate an error.
case storage::kFileSystemTypeProvided:
case storage::kFileSystemTypeNativeForPlatformApp:
// For now, we don't support serializing handles for Chrome OS specific
// types, run |callback| with an empty vector to indicate an error.
std::move(callback).Run({});
return;
#endif
default:
NOTREACHED();
}
......@@ -851,22 +868,22 @@ NativeFileSystemManagerImpl::CreateFileSystemURLFromPath(
DCHECK(isolated_context);
FileSystemURLAndFSHandle result;
std::string filesystem_id;
storage::FileSystemType fs_type = storage::kFileSystemTypeNativeLocal;
#if defined(OS_CHROMEOS)
// TODO(crbug.com/1093653): Support Chrome OS File System Provider in all Web
// Apps. For now, we only support FSP for WebUIs.
bool is_web_ui = HasWebUIScheme(origin.GetURL());
// Check the path prefix to determine if a file is provided by FSP API.
bool is_provided_path =
base::StartsWith(path.AsUTF8Unsafe(), kProvidedMountPointRoot,
base::CompareCase::SENSITIVE);
if (is_web_ui && is_provided_path)
fs_type = storage::kFileSystemTypeNativeForPlatformApp;
// Apps. For now, we only support external filesystem types for WebUIs.
if (HasWebUIScheme(origin.GetURL())) {
storage::FileSystemType cracked_fs_type =
GetFileSystemTypeForCrackedPath(path, &filesystem_id);
if (cracked_fs_type != storage::kFileSystemTypeUnknown)
fs_type = cracked_fs_type;
}
#endif
result.file_system = isolated_context->RegisterFileSystemForPath(
fs_type, std::string(), path, &result.base_name);
fs_type, filesystem_id, path, &result.base_name);
base::FilePath root_path =
isolated_context->CreateVirtualRootPath(result.file_system.id());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment