Index: chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc |
diff --git a/chrome/browser/extensions/api/file_system/file_system_api.cc b/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc |
similarity index 13% |
copy from chrome/browser/extensions/api/file_system/file_system_api.cc |
copy to chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc |
index 8d5c628b3b36e0d2ba4dbdfb7cea602191b59580..c50da13a2143626a0d8e953e77b287ba455703ad 100644 |
--- a/chrome/browser/extensions/api/file_system/file_system_api.cc |
+++ b/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc |
@@ -1,64 +1,46 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "chrome/browser/extensions/api/file_system/file_system_api.h" |
+#include "chrome/browser/extensions/api/file_system/chrome_file_system_delegate.h" |
-#include <stddef.h> |
- |
-#include <memory> |
-#include <set> |
#include <utility> |
#include <vector> |
-#include "apps/saved_files_service.h" |
+#include "apps/saved_files_service_delegate_impl.h" |
#include "base/bind.h" |
+#include "base/callback.h" |
#include "base/files/file_path.h" |
-#include "base/files/file_util.h" |
-#include "base/macros.h" |
+#include "base/logging.h" |
#include "base/memory/ptr_util.h" |
#include "base/path_service.h" |
-#include "base/strings/string_util.h" |
-#include "base/strings/stringprintf.h" |
-#include "base/strings/sys_string_conversions.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "base/task_scheduler/post_task.h" |
-#include "base/value_conversions.h" |
-#include "base/values.h" |
-#include "build/build_config.h" |
+#include "base/strings/string16.h" |
#include "chrome/browser/platform_util.h" |
#include "chrome/browser/profiles/profile.h" |
#include "chrome/browser/ui/apps/directory_access_confirmation_dialog.h" |
#include "chrome/browser/ui/chrome_select_file_policy.h" |
#include "chrome/common/chrome_paths.h" |
-#include "chrome/common/extensions/api/file_system.h" |
#include "chrome/grit/generated_resources.h" |
-#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/browser_context.h" |
#include "content/public/browser/child_process_security_policy.h" |
#include "content/public/browser/render_frame_host.h" |
#include "content/public/browser/render_process_host.h" |
#include "content/public/browser/storage_partition.h" |
#include "content/public/browser/web_contents.h" |
#include "extensions/browser/api/file_handlers/app_file_handler_util.h" |
-#include "extensions/browser/app_window/app_window.h" |
-#include "extensions/browser/app_window/app_window_registry.h" |
+#include "extensions/browser/api/file_system/saved_files_service_delegate.h" |
+#include "extensions/browser/extension_function.h" |
#include "extensions/browser/extension_prefs.h" |
#include "extensions/browser/extension_system.h" |
#include "extensions/browser/extension_util.h" |
-#include "extensions/browser/granted_file_entry.h" |
-#include "extensions/browser/path_util.h" |
-#include "extensions/common/permissions/api_permission.h" |
-#include "extensions/common/permissions/permissions_data.h" |
-#include "net/base/mime_util.h" |
+#include "extensions/common/api/file_system.h" |
+#include "extensions/common/extension.h" |
#include "storage/browser/fileapi/external_mount_points.h" |
-#include "storage/browser/fileapi/file_system_operation_runner.h" |
#include "storage/browser/fileapi/isolated_context.h" |
#include "storage/common/fileapi/file_system_types.h" |
#include "storage/common/fileapi/file_system_util.h" |
-#include "ui/base/l10n/l10n_util.h" |
-#include "ui/base/ui_base_types.h" |
#include "ui/shell_dialogs/select_file_dialog.h" |
-#include "ui/shell_dialogs/selected_file_info.h" |
+#include "ui/shell_dialogs/select_file_policy.h" |
#if defined(OS_MACOSX) |
#include <CoreFoundation/CoreFoundation.h> |
@@ -66,8 +48,6 @@ |
#endif |
#if defined(OS_CHROMEOS) |
-#include "base/strings/string16.h" |
-#include "chrome/browser/chromeos/file_manager/filesystem_api_util.h" |
#include "chrome/browser/chromeos/file_manager/volume_manager.h" |
#include "extensions/browser/event_router.h" |
#include "extensions/browser/extension_registry.h" |
@@ -75,207 +55,61 @@ |
#include "url/url_constants.h" |
#endif |
-using apps::SavedFileEntry; |
-using apps::SavedFilesService; |
-using storage::IsolatedContext; |
- |
-const char kInvalidCallingPage[] = |
- "Invalid calling page. " |
- "This function can't be called from a background page."; |
-const char kUserCancelled[] = "User cancelled"; |
-const char kWritableFileErrorFormat[] = "Error opening %s"; |
-const char kRequiresFileSystemWriteError[] = |
- "Operation requires fileSystem.write permission"; |
-const char kRequiresFileSystemDirectoryError[] = |
- "Operation requires fileSystem.directory permission"; |
-const char kMultipleUnsupportedError[] = |
- "acceptsMultiple: true is only supported for 'openFile'"; |
-const char kUnknownIdError[] = "Unknown id"; |
- |
-#if !defined(OS_CHROMEOS) |
-const char kNotSupportedOnCurrentPlatformError[] = |
- "Operation not supported on the current platform."; |
-#else |
-const char kNotSupportedOnNonKioskSessionError[] = |
- "Operation only supported for kiosk apps running in a kiosk session."; |
-const char kVolumeNotFoundError[] = "Volume not found."; |
-const char kSecurityError[] = "Security error."; |
-const char kConsentImpossible[] = |
- "Impossible to ask for user consent as there is no app window visible."; |
-#endif |
- |
namespace extensions { |
namespace file_system = api::file_system; |
-namespace ChooseEntry = file_system::ChooseEntry; |
- |
-namespace { |
- |
-bool g_skip_picker_for_test = false; |
-bool g_use_suggested_path_for_test = false; |
-base::FilePath* g_path_to_be_picked_for_test; |
-std::vector<base::FilePath>* g_paths_to_be_picked_for_test; |
-bool g_skip_directory_confirmation_for_test = false; |
-bool g_allow_directory_access_for_test = false; |
- |
-// Expand the mime-types and extensions provided in an AcceptOption, returning |
-// them within the passed extension vector. Returns false if no valid types |
-// were found. |
-bool GetFileTypesFromAcceptOption( |
- const file_system::AcceptOption& accept_option, |
- std::vector<base::FilePath::StringType>* extensions, |
- base::string16* description) { |
- std::set<base::FilePath::StringType> extension_set; |
- int description_id = 0; |
- |
- if (accept_option.mime_types.get()) { |
- std::vector<std::string>* list = accept_option.mime_types.get(); |
- bool valid_type = false; |
- for (std::vector<std::string>::const_iterator iter = list->begin(); |
- iter != list->end(); ++iter) { |
- std::vector<base::FilePath::StringType> inner; |
- std::string accept_type = base::ToLowerASCII(*iter); |
- net::GetExtensionsForMimeType(accept_type, &inner); |
- if (inner.empty()) |
- continue; |
- |
- if (valid_type) |
- description_id = 0; // We already have an accept type with label; if |
- // we find another, give up and use the default. |
- else if (accept_type == "image/*") |
- description_id = IDS_IMAGE_FILES; |
- else if (accept_type == "audio/*") |
- description_id = IDS_AUDIO_FILES; |
- else if (accept_type == "video/*") |
- description_id = IDS_VIDEO_FILES; |
- |
- extension_set.insert(inner.begin(), inner.end()); |
- valid_type = true; |
- } |
- } |
- |
- if (accept_option.extensions.get()) { |
- std::vector<std::string>* list = accept_option.extensions.get(); |
- for (std::vector<std::string>::const_iterator iter = list->begin(); |
- iter != list->end(); ++iter) { |
- std::string extension = base::ToLowerASCII(*iter); |
-#if defined(OS_WIN) |
- extension_set.insert(base::UTF8ToWide(*iter)); |
-#else |
- extension_set.insert(*iter); |
-#endif |
- } |
- } |
- |
- extensions->assign(extension_set.begin(), extension_set.end()); |
- if (extensions->empty()) |
- return false; |
- |
- if (accept_option.description.get()) |
- *description = base::UTF8ToUTF16(*accept_option.description); |
- else if (description_id) |
- *description = l10n_util::GetStringUTF16(description_id); |
- |
- return true; |
-} |
-// Key for the path of the directory of the file last chosen by the user in |
-// response to a chrome.fileSystem.chooseEntry() call. |
-const char kLastChooseEntryDirectory[] = "last_choose_file_directory"; |
- |
-const int kGraylistedPaths[] = { |
- base::DIR_HOME, |
-#if defined(OS_WIN) |
- base::DIR_PROGRAM_FILES, base::DIR_PROGRAM_FILESX86, base::DIR_WINDOWS, |
-#endif |
-}; |
- |
-typedef base::Callback<void(std::unique_ptr<base::File::Info>)> |
- FileInfoOptCallback; |
+#if defined(OS_CHROMEOS) |
+using file_system_api::ConsentProvider; |
+using file_system_api::ConsentProviderDelegate; |
-// Passes optional file info to the UI thread depending on |result| and |info|. |
-void PassFileInfoToUIThread(const FileInfoOptCallback& callback, |
- base::File::Error result, |
- const base::File::Info& info) { |
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
- std::unique_ptr<base::File::Info> file_info( |
- result == base::File::FILE_OK ? new base::File::Info(info) : NULL); |
- content::BrowserThread::PostTask( |
- content::BrowserThread::UI, FROM_HERE, |
- base::BindOnce(callback, base::Passed(&file_info))); |
-} |
+namespace { |
-// Gets a WebContents instance handle for a platform app hosted in |
-// |render_frame_host|. If not found, then returns NULL. |
-content::WebContents* GetWebContentsForRenderFrameHost( |
- Profile* profile, |
- content::RenderFrameHost* render_frame_host) { |
- content::WebContents* web_contents = |
- content::WebContents::FromRenderFrameHost(render_frame_host); |
- // Check if there is an app window associated with the web contents; if not, |
- // return null. |
- return AppWindowRegistry::Get(profile)->GetAppWindowForWebContents( |
- web_contents) |
- ? web_contents |
- : nullptr; |
-} |
+const char kConsentImpossible[] = |
+ "Impossible to ask for user consent as there is no app window visible."; |
+const char kNotSupportedOnNonKioskSessionError[] = |
+ "Operation only supported for kiosk apps running in a kiosk session."; |
+const char kRequiresFileSystemWriteError[] = |
+ "Operation requires fileSystem.write permission"; |
+const char kSecurityError[] = "Security error."; |
+const char kVolumeNotFoundError[] = "Volume not found."; |
-#if defined(OS_CHROMEOS) |
// Fills a list of volumes mounted in the system. |
-void FillVolumeList(Profile* profile, |
- std::vector<api::file_system::Volume>* result) { |
+void FillVolumeList(content::BrowserContext* browser_context, |
+ std::vector<file_system::Volume>* result) { |
file_manager::VolumeManager* const volume_manager = |
- file_manager::VolumeManager::Get(profile); |
+ file_manager::VolumeManager::Get(browser_context); |
DCHECK(volume_manager); |
const auto& volume_list = volume_manager->GetVolumeList(); |
// Convert volume_list to result_volume_list. |
for (const auto& volume : volume_list) { |
- api::file_system::Volume result_volume; |
+ file_system::Volume result_volume; |
result_volume.volume_id = volume->volume_id(); |
result_volume.writable = !volume->is_read_only(); |
result->push_back(std::move(result_volume)); |
} |
} |
-#endif |
} // namespace |
namespace file_system_api { |
-base::FilePath GetLastChooseEntryDirectory(const ExtensionPrefs* prefs, |
- const std::string& extension_id) { |
- base::FilePath path; |
- std::string string_path; |
- if (prefs->ReadPrefAsString(extension_id, kLastChooseEntryDirectory, |
- &string_path)) { |
- path = base::FilePath::FromUTF8Unsafe(string_path); |
- } |
- return path; |
-} |
- |
-void SetLastChooseEntryDirectory(ExtensionPrefs* prefs, |
- const std::string& extension_id, |
- const base::FilePath& path) { |
- prefs->UpdateExtensionPref(extension_id, kLastChooseEntryDirectory, |
- base::CreateFilePathValue(path)); |
-} |
- |
-#if defined(OS_CHROMEOS) |
-void DispatchVolumeListChangeEvent(Profile* profile) { |
- DCHECK(profile); |
- EventRouter* const event_router = EventRouter::Get(profile); |
+void DispatchVolumeListChangeEvent(content::BrowserContext* browser_context) { |
+ DCHECK(browser_context); |
+ EventRouter* const event_router = EventRouter::Get(browser_context); |
if (!event_router) // Possible on shutdown. |
return; |
- ExtensionRegistry* const registry = ExtensionRegistry::Get(profile); |
+ ExtensionRegistry* const registry = ExtensionRegistry::Get(browser_context); |
if (!registry) // Possible on shutdown. |
return; |
- ConsentProviderDelegate consent_provider_delegate(profile, nullptr); |
+ ConsentProviderDelegate consent_provider_delegate( |
+ Profile::FromBrowserContext(browser_context)); |
ConsentProvider consent_provider(&consent_provider_delegate); |
- api::file_system::VolumeListChangedEvent event_args; |
- FillVolumeList(profile, &event_args.volumes); |
+ file_system::VolumeListChangedEvent event_args; |
+ FillVolumeList(browser_context, &event_args.volumes); |
for (const auto& extension : registry->enabled_extensions()) { |
if (!consent_provider.IsGrantable(*extension.get())) |
continue; |
@@ -283,839 +117,168 @@ void DispatchVolumeListChangeEvent(Profile* profile) { |
extension->id(), |
base::MakeUnique<Event>( |
events::FILE_SYSTEM_ON_VOLUME_LIST_CHANGED, |
- api::file_system::OnVolumeListChanged::kEventName, |
- api::file_system::OnVolumeListChanged::Create(event_args))); |
+ file_system::OnVolumeListChanged::kEventName, |
+ file_system::OnVolumeListChanged::Create(event_args))); |
} |
} |
-#endif |
} // namespace file_system_api |
+#endif // defined(OS_CHROMEOS) |
-#if defined(OS_CHROMEOS) |
-using file_system_api::ConsentProvider; |
-#endif |
- |
-ExtensionFunction::ResponseAction FileSystemGetDisplayPathFunction::Run() { |
- std::string filesystem_name; |
- std::string filesystem_path; |
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); |
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); |
+ChromeFileSystemDelegate::ChromeFileSystemDelegate() {} |
- base::FilePath file_path; |
- std::string error; |
- if (!app_file_handler_util::ValidateFileEntryAndGetPath( |
- filesystem_name, filesystem_path, |
- render_frame_host()->GetProcess()->GetID(), &file_path, &error)) { |
- return RespondNow(Error(error)); |
- } |
+ChromeFileSystemDelegate::~ChromeFileSystemDelegate() {} |
- file_path = path_util::PrettifyPath(file_path); |
- return RespondNow( |
- OneArgument(base::MakeUnique<base::Value>(file_path.value()))); |
+base::FilePath ChromeFileSystemDelegate::GetDefaultDirectory() { |
+ base::FilePath documents_dir; |
+ PathService::Get(chrome::DIR_USER_DOCUMENTS, &documents_dir); |
+ return documents_dir; |
} |
-FileSystemEntryFunction::FileSystemEntryFunction() |
- : multiple_(false), is_directory_(false) {} |
- |
-void FileSystemEntryFunction::PrepareFilesForWritableApp( |
- const std::vector<base::FilePath>& paths) { |
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
- // TODO(cmihail): Path directory set should be initialized only with the |
- // paths that are actually directories, but for now we will consider |
- // all paths directories in case is_directory_ is true, otherwise |
- // all paths files, as this was the previous logic. |
- std::set<base::FilePath> path_directory_set_ = |
- is_directory_ ? std::set<base::FilePath>(paths.begin(), paths.end()) |
- : std::set<base::FilePath>{}; |
- app_file_handler_util::PrepareFilesForWritableApp( |
- paths, GetProfile(), path_directory_set_, |
- base::Bind(&FileSystemEntryFunction::RegisterFileSystemsAndSendResponse, |
- this, paths), |
- base::Bind(&FileSystemEntryFunction::HandleWritableFileError, this)); |
+std::unique_ptr<ui::SelectFilePolicy> |
+ChromeFileSystemDelegate::CreateSelectFilePolicy( |
+ content::WebContents* web_contents) { |
+ return base::MakeUnique<ChromeSelectFilePolicy>(web_contents); |
} |
-void FileSystemEntryFunction::RegisterFileSystemsAndSendResponse( |
- const std::vector<base::FilePath>& paths) { |
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
- if (!render_frame_host()) |
- return; |
- |
- std::unique_ptr<base::DictionaryValue> result = CreateResult(); |
- for (const auto& path : paths) |
- AddEntryToResult(path, std::string(), result.get()); |
- SetResult(std::move(result)); |
- SendResponse(true); |
+scoped_refptr<ui::SelectFileDialog> |
+ChromeFileSystemDelegate::CreateSelectFileDialog( |
+ ui::SelectFileDialog::Listener* listener, |
+ std::unique_ptr<ui::SelectFilePolicy> policy) { |
+ // SelectFileDialog will take ownership of |policy|. |
+ return ui::SelectFileDialog::Create(listener, policy.release()); |
} |
-std::unique_ptr<base::DictionaryValue> FileSystemEntryFunction::CreateResult() { |
- std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); |
- result->Set("entries", base::MakeUnique<base::ListValue>()); |
- result->SetBoolean("multiple", multiple_); |
- return result; |
+void ChromeFileSystemDelegate::ShowSelectFileDialogForWebContents( |
+ scoped_refptr<ui::SelectFileDialog> dialog, |
+ content::WebContents* web_contents, |
+ ui::SelectFileDialog::Type type, |
+ const base::FilePath& default_path, |
+ const ui::SelectFileDialog::FileTypeInfo* file_types) { |
+ gfx::NativeWindow owning_window = |
+ web_contents ? platform_util::GetTopLevel(web_contents->GetNativeView()) |
+ : nullptr; |
+ dialog->SelectFile(type, base::string16(), default_path, file_types, 0, |
+ base::FilePath::StringType(), owning_window, nullptr); |
} |
-void FileSystemEntryFunction::AddEntryToResult(const base::FilePath& path, |
- const std::string& id_override, |
- base::DictionaryValue* result) { |
- GrantedFileEntry file_entry = app_file_handler_util::CreateFileEntry( |
- GetProfile(), extension(), render_frame_host()->GetProcess()->GetID(), |
- path, is_directory_); |
- base::ListValue* entries; |
- bool success = result->GetList("entries", &entries); |
- DCHECK(success); |
- |
- std::unique_ptr<base::DictionaryValue> entry(new base::DictionaryValue()); |
- entry->SetString("fileSystemId", file_entry.filesystem_id); |
- entry->SetString("baseName", file_entry.registered_name); |
- if (id_override.empty()) |
- entry->SetString("id", file_entry.id); |
+void ChromeFileSystemDelegate::ConfirmSensitiveDirectoryAccess( |
+ bool writable, |
+ const base::string16& app_name, |
+ content::WebContents* web_contents, |
+ const base::Closure& on_accept, |
+ const base::Closure& on_cancel) { |
+ CreateDirectoryAccessConfirmationDialog(writable, app_name, web_contents, |
+ on_accept, on_cancel); |
+} |
+ |
+bool ChromeFileSystemDelegate::GetDescriptionIdForAcceptType( |
+ const std::string& accept_type, |
+ int* description_id) { |
+ if (accept_type == "image/*") |
+ *description_id = IDS_IMAGE_FILES; |
+ else if (accept_type == "audio/*") |
+ *description_id = IDS_AUDIO_FILES; |
+ else if (accept_type == "video/*") |
+ *description_id = IDS_VIDEO_FILES; |
else |
- entry->SetString("id", id_override); |
- entry->SetBoolean("isDirectory", is_directory_); |
- entries->Append(std::move(entry)); |
-} |
- |
-void FileSystemEntryFunction::HandleWritableFileError( |
- const base::FilePath& error_path) { |
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
- error_ = base::StringPrintf(kWritableFileErrorFormat, |
- error_path.BaseName().AsUTF8Unsafe().c_str()); |
- SendResponse(false); |
-} |
- |
-bool FileSystemGetWritableEntryFunction::RunAsync() { |
- std::string filesystem_name; |
- std::string filesystem_path; |
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); |
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); |
- |
- if (!app_file_handler_util::HasFileSystemWritePermission(extension_.get())) { |
- error_ = kRequiresFileSystemWriteError; |
- return false; |
- } |
- |
- if (!app_file_handler_util::ValidateFileEntryAndGetPath( |
- filesystem_name, filesystem_path, |
- render_frame_host()->GetProcess()->GetID(), &path_, &error_)) |
return false; |
- |
- base::PostTaskWithTraitsAndReply( |
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, |
- base::BindOnce(&FileSystemGetWritableEntryFunction::SetIsDirectoryAsync, |
- this), |
- base::BindOnce( |
- &FileSystemGetWritableEntryFunction::CheckPermissionAndSendResponse, |
- this)); |
return true; |
} |
-void FileSystemGetWritableEntryFunction::CheckPermissionAndSendResponse() { |
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
- if (is_directory_ && !extension_->permissions_data()->HasAPIPermission( |
- APIPermission::kFileSystemDirectory)) { |
- error_ = kRequiresFileSystemDirectoryError; |
- SendResponse(false); |
- } |
- std::vector<base::FilePath> paths; |
- paths.push_back(path_); |
- PrepareFilesForWritableApp(paths); |
-} |
- |
-void FileSystemGetWritableEntryFunction::SetIsDirectoryAsync() { |
- if (base::DirectoryExists(path_)) { |
- is_directory_ = true; |
- } |
-} |
- |
-ExtensionFunction::ResponseAction FileSystemIsWritableEntryFunction::Run() { |
- std::string filesystem_name; |
- std::string filesystem_path; |
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); |
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); |
- |
- std::string filesystem_id; |
- if (!storage::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id)) |
- return RespondNow(Error(app_file_handler_util::kInvalidParameters)); |
- |
- content::ChildProcessSecurityPolicy* policy = |
- content::ChildProcessSecurityPolicy::GetInstance(); |
- int renderer_id = render_frame_host()->GetProcess()->GetID(); |
- bool is_writable = policy->CanReadWriteFileSystem(renderer_id, filesystem_id); |
- |
- return RespondNow(OneArgument(base::MakeUnique<base::Value>(is_writable))); |
-} |
- |
-// Handles showing a dialog to the user to ask for the filename for a file to |
-// save or open. |
-class FileSystemChooseEntryFunction::FilePicker |
- : public ui::SelectFileDialog::Listener { |
- public: |
- FilePicker(FileSystemChooseEntryFunction* function, |
- content::WebContents* web_contents, |
- const base::FilePath& suggested_name, |
- const ui::SelectFileDialog::FileTypeInfo& file_type_info, |
- ui::SelectFileDialog::Type picker_type) |
- : function_(function) { |
- select_file_dialog_ = ui::SelectFileDialog::Create( |
- this, new ChromeSelectFilePolicy(web_contents)); |
- gfx::NativeWindow owning_window = |
- web_contents ? platform_util::GetTopLevel(web_contents->GetNativeView()) |
- : NULL; |
- |
- if (g_skip_picker_for_test) { |
- if (g_use_suggested_path_for_test) { |
- content::BrowserThread::PostTask( |
- content::BrowserThread::UI, FROM_HERE, |
- base::BindOnce( |
- &FileSystemChooseEntryFunction::FilePicker::FileSelected, |
- base::Unretained(this), suggested_name, 1, |
- static_cast<void*>(NULL))); |
- } else if (g_path_to_be_picked_for_test) { |
- content::BrowserThread::PostTask( |
- content::BrowserThread::UI, FROM_HERE, |
- base::BindOnce( |
- &FileSystemChooseEntryFunction::FilePicker::FileSelected, |
- base::Unretained(this), *g_path_to_be_picked_for_test, 1, |
- static_cast<void*>(NULL))); |
- } else if (g_paths_to_be_picked_for_test) { |
- content::BrowserThread::PostTask( |
- content::BrowserThread::UI, FROM_HERE, |
- base::BindOnce( |
- &FileSystemChooseEntryFunction::FilePicker::MultiFilesSelected, |
- base::Unretained(this), *g_paths_to_be_picked_for_test, |
- static_cast<void*>(NULL))); |
- } else { |
- content::BrowserThread::PostTask( |
- content::BrowserThread::UI, FROM_HERE, |
- base::BindOnce(&FileSystemChooseEntryFunction::FilePicker:: |
- FileSelectionCanceled, |
- base::Unretained(this), static_cast<void*>(NULL))); |
- } |
- return; |
- } |
- |
- select_file_dialog_->SelectFile( |
- picker_type, base::string16(), suggested_name, &file_type_info, 0, |
- base::FilePath::StringType(), owning_window, NULL); |
- } |
- |
- ~FilePicker() override {} |
- |
- private: |
- // ui::SelectFileDialog::Listener implementation. |
- void FileSelected(const base::FilePath& path, |
- int index, |
- void* params) override { |
- std::vector<base::FilePath> paths; |
- paths.push_back(path); |
- MultiFilesSelected(paths, params); |
- } |
- |
- void FileSelectedWithExtraInfo(const ui::SelectedFileInfo& file, |
- int index, |
- void* params) override { |
- // Normally, file.local_path is used because it is a native path to the |
- // local read-only cached file in the case of remote file system like |
- // Chrome OS's Google Drive integration. Here, however, |file.file_path| is |
- // necessary because we need to create a FileEntry denoting the remote file, |
- // not its cache. On other platforms than Chrome OS, they are the same. |
- // |
- // TODO(kinaba): remove this, once after the file picker implements proper |
- // switch of the path treatment depending on the |allowed_paths|. |
- FileSelected(file.file_path, index, params); |
- } |
- |
- void MultiFilesSelected(const std::vector<base::FilePath>& files, |
- void* params) override { |
- function_->FilesSelected(files); |
- delete this; |
- } |
- |
- void MultiFilesSelectedWithExtraInfo( |
- const std::vector<ui::SelectedFileInfo>& files, |
- void* params) override { |
- std::vector<base::FilePath> paths; |
- for (std::vector<ui::SelectedFileInfo>::const_iterator it = files.begin(); |
- it != files.end(); ++it) { |
- paths.push_back(it->file_path); |
- } |
- MultiFilesSelected(paths, params); |
- } |
- |
- void FileSelectionCanceled(void* params) override { |
- function_->FileSelectionCanceled(); |
- delete this; |
- } |
- |
- scoped_refptr<ui::SelectFileDialog> select_file_dialog_; |
- scoped_refptr<FileSystemChooseEntryFunction> function_; |
- |
- DISALLOW_COPY_AND_ASSIGN(FilePicker); |
-}; |
- |
-void FileSystemChooseEntryFunction::ShowPicker( |
- const ui::SelectFileDialog::FileTypeInfo& file_type_info, |
- ui::SelectFileDialog::Type picker_type) { |
- // TODO(asargent/benwells) - As a short term remediation for crbug.com/179010 |
- // we're adding the ability for a whitelisted extension to use this API since |
- // chrome.fileBrowserHandler.selectFile is ChromeOS-only. Eventually we'd |
- // like a better solution and likely this code will go back to being |
- // platform-app only. |
- content::WebContents* const web_contents = |
- extension_->is_platform_app() |
- ? GetWebContentsForRenderFrameHost(GetProfile(), render_frame_host()) |
- : GetAssociatedWebContents(); |
- if (!web_contents) { |
- error_ = kInvalidCallingPage; |
- SendResponse(false); |
- return; |
- } |
- |
- // The file picker will hold a reference to this function instance, preventing |
- // its destruction (and subsequent sending of the function response) until the |
- // user has selected a file or cancelled the picker. At that point, the picker |
- // will delete itself, which will also free the function instance. |
- new FilePicker(this, web_contents, initial_path_, file_type_info, |
- picker_type); |
-} |
- |
-// static |
-void FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest( |
- base::FilePath* path) { |
- g_skip_picker_for_test = true; |
- g_use_suggested_path_for_test = false; |
- g_path_to_be_picked_for_test = path; |
- g_paths_to_be_picked_for_test = NULL; |
-} |
- |
-void FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathsForTest( |
- std::vector<base::FilePath>* paths) { |
- g_skip_picker_for_test = true; |
- g_use_suggested_path_for_test = false; |
- g_paths_to_be_picked_for_test = paths; |
-} |
- |
-// static |
-void FileSystemChooseEntryFunction::SkipPickerAndSelectSuggestedPathForTest() { |
- g_skip_picker_for_test = true; |
- g_use_suggested_path_for_test = true; |
- g_path_to_be_picked_for_test = NULL; |
- g_paths_to_be_picked_for_test = NULL; |
-} |
- |
-// static |
-void FileSystemChooseEntryFunction::SkipPickerAndAlwaysCancelForTest() { |
- g_skip_picker_for_test = true; |
- g_use_suggested_path_for_test = false; |
- g_path_to_be_picked_for_test = NULL; |
- g_paths_to_be_picked_for_test = NULL; |
-} |
- |
-// static |
-void FileSystemChooseEntryFunction::StopSkippingPickerForTest() { |
- g_skip_picker_for_test = false; |
-} |
- |
-// static |
-void FileSystemChooseEntryFunction::SkipDirectoryConfirmationForTest() { |
- g_skip_directory_confirmation_for_test = true; |
- g_allow_directory_access_for_test = true; |
-} |
- |
-// static |
-void FileSystemChooseEntryFunction::AutoCancelDirectoryConfirmationForTest() { |
- g_skip_directory_confirmation_for_test = true; |
- g_allow_directory_access_for_test = false; |
-} |
- |
-// static |
-void FileSystemChooseEntryFunction::StopSkippingDirectoryConfirmationForTest() { |
- g_skip_directory_confirmation_for_test = false; |
-} |
- |
-// static |
-void FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest( |
- const std::string& name, |
- const base::FilePath& path) { |
- // For testing on Chrome OS, where to deal with remote and local paths |
- // smoothly, all accessed paths need to be registered in the list of |
- // external mount points. |
- storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( |
- name, storage::kFileSystemTypeNativeLocal, |
- storage::FileSystemMountOption(), path); |
-} |
- |
-void FileSystemChooseEntryFunction::FilesSelected( |
- const std::vector<base::FilePath>& paths) { |
- DCHECK(!paths.empty()); |
- base::FilePath last_choose_directory; |
- if (is_directory_) { |
- last_choose_directory = paths[0]; |
- } else { |
- last_choose_directory = paths[0].DirName(); |
- } |
- file_system_api::SetLastChooseEntryDirectory( |
- ExtensionPrefs::Get(GetProfile()), extension()->id(), |
- last_choose_directory); |
- if (is_directory_) { |
- // Get the WebContents for the app window to be the parent window of the |
- // confirmation dialog if necessary. |
- content::WebContents* const web_contents = |
- GetWebContentsForRenderFrameHost(GetProfile(), render_frame_host()); |
- if (!web_contents) { |
- error_ = kInvalidCallingPage; |
- SendResponse(false); |
- return; |
- } |
- |
- DCHECK_EQ(paths.size(), 1u); |
- bool non_native_path = false; |
-#if defined(OS_CHROMEOS) |
- non_native_path = |
- file_manager::util::IsUnderNonNativeLocalPath(GetProfile(), paths[0]); |
-#endif |
- |
- base::PostTaskWithTraits( |
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, |
- base::BindOnce( |
- &FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync, this, |
- non_native_path, paths, web_contents)); |
- return; |
- } |
- |
- OnDirectoryAccessConfirmed(paths); |
-} |
- |
-void FileSystemChooseEntryFunction::FileSelectionCanceled() { |
- error_ = kUserCancelled; |
- SendResponse(false); |
-} |
- |
-void FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync( |
- bool non_native_path, |
- const std::vector<base::FilePath>& paths, |
- content::WebContents* web_contents) { |
- const base::FilePath check_path = |
- non_native_path ? paths[0] : base::MakeAbsoluteFilePath(paths[0]); |
- if (check_path.empty()) { |
- content::BrowserThread::PostTask( |
- content::BrowserThread::UI, FROM_HERE, |
- base::BindOnce(&FileSystemChooseEntryFunction::FileSelectionCanceled, |
- this)); |
- return; |
- } |
- |
- for (size_t i = 0; i < arraysize(kGraylistedPaths); i++) { |
- base::FilePath graylisted_path; |
- if (PathService::Get(kGraylistedPaths[i], &graylisted_path) && |
- (check_path == graylisted_path || |
- check_path.IsParent(graylisted_path))) { |
- if (g_skip_directory_confirmation_for_test) { |
- if (g_allow_directory_access_for_test) { |
- break; |
- } else { |
- content::BrowserThread::PostTask( |
- content::BrowserThread::UI, FROM_HERE, |
- base::BindOnce( |
- &FileSystemChooseEntryFunction::FileSelectionCanceled, this)); |
- } |
- return; |
- } |
- |
- content::BrowserThread::PostTask( |
- content::BrowserThread::UI, FROM_HERE, |
- base::BindOnce( |
- CreateDirectoryAccessConfirmationDialog, |
- app_file_handler_util::HasFileSystemWritePermission( |
- extension_.get()), |
- base::UTF8ToUTF16(extension_->name()), web_contents, |
- base::Bind( |
- &FileSystemChooseEntryFunction::OnDirectoryAccessConfirmed, |
- this, paths), |
- base::Bind(&FileSystemChooseEntryFunction::FileSelectionCanceled, |
- this))); |
- return; |
- } |
- } |
- |
- content::BrowserThread::PostTask( |
- content::BrowserThread::UI, FROM_HERE, |
- base::BindOnce(&FileSystemChooseEntryFunction::OnDirectoryAccessConfirmed, |
- this, paths)); |
-} |
- |
-void FileSystemChooseEntryFunction::OnDirectoryAccessConfirmed( |
- const std::vector<base::FilePath>& paths) { |
- if (app_file_handler_util::HasFileSystemWritePermission(extension_.get())) { |
- PrepareFilesForWritableApp(paths); |
- return; |
- } |
- |
- // Don't need to check the file, it's for reading. |
- RegisterFileSystemsAndSendResponse(paths); |
-} |
- |
-void FileSystemChooseEntryFunction::BuildFileTypeInfo( |
- ui::SelectFileDialog::FileTypeInfo* file_type_info, |
- const base::FilePath::StringType& suggested_extension, |
- const AcceptOptions* accepts, |
- const bool* acceptsAllTypes) { |
- file_type_info->include_all_files = true; |
- if (acceptsAllTypes) |
- file_type_info->include_all_files = *acceptsAllTypes; |
- |
- bool need_suggestion = |
- !file_type_info->include_all_files && !suggested_extension.empty(); |
- |
- if (accepts) { |
- for (const file_system::AcceptOption& option : *accepts) { |
- base::string16 description; |
- std::vector<base::FilePath::StringType> extensions; |
- |
- if (!GetFileTypesFromAcceptOption(option, &extensions, &description)) |
- continue; // No extensions were found. |
- |
- file_type_info->extensions.push_back(extensions); |
- file_type_info->extension_description_overrides.push_back(description); |
- |
- // If we still need to find suggested_extension, hunt for it inside the |
- // extensions returned from GetFileTypesFromAcceptOption. |
- if (need_suggestion && |
- std::find(extensions.begin(), extensions.end(), |
- suggested_extension) != extensions.end()) { |
- need_suggestion = false; |
- } |
- } |
- } |
- |
- // If there's nothing in our accepted extension list or we couldn't find the |
- // suggested extension required, then default to accepting all types. |
- if (file_type_info->extensions.empty() || need_suggestion) |
- file_type_info->include_all_files = true; |
-} |
- |
-void FileSystemChooseEntryFunction::BuildSuggestion( |
- const std::string* opt_name, |
- base::FilePath* suggested_name, |
- base::FilePath::StringType* suggested_extension) { |
- if (opt_name) { |
- *suggested_name = base::FilePath::FromUTF8Unsafe(*opt_name); |
- |
- // Don't allow any path components; shorten to the base name. This should |
- // result in a relative path, but in some cases may not. Clear the |
- // suggestion for safety if this is the case. |
- *suggested_name = suggested_name->BaseName(); |
- if (suggested_name->IsAbsolute()) |
- *suggested_name = base::FilePath(); |
- |
- *suggested_extension = suggested_name->Extension(); |
- if (!suggested_extension->empty()) |
- suggested_extension->erase(suggested_extension->begin()); // drop the . |
- } |
-} |
- |
-void FileSystemChooseEntryFunction::SetInitialPathAndShowPicker( |
- const base::FilePath& previous_path, |
- const base::FilePath& suggested_name, |
- const ui::SelectFileDialog::FileTypeInfo& file_type_info, |
- ui::SelectFileDialog::Type picker_type, |
- bool is_previous_path_directory) { |
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
- if (is_previous_path_directory) { |
- initial_path_ = previous_path.Append(suggested_name); |
- } else { |
- base::FilePath documents_dir; |
- if (PathService::Get(chrome::DIR_USER_DOCUMENTS, &documents_dir)) { |
- initial_path_ = documents_dir.Append(suggested_name); |
- } else { |
- initial_path_ = suggested_name; |
- } |
- } |
- ShowPicker(file_type_info, picker_type); |
-} |
- |
-bool FileSystemChooseEntryFunction::RunAsync() { |
- std::unique_ptr<ChooseEntry::Params> params( |
- ChooseEntry::Params::Create(*args_)); |
- EXTENSION_FUNCTION_VALIDATE(params.get()); |
- |
- base::FilePath suggested_name; |
- ui::SelectFileDialog::FileTypeInfo file_type_info; |
- ui::SelectFileDialog::Type picker_type = |
- ui::SelectFileDialog::SELECT_OPEN_FILE; |
- |
- file_system::ChooseEntryOptions* options = params->options.get(); |
- if (options) { |
- multiple_ = options->accepts_multiple && *options->accepts_multiple; |
- if (multiple_) |
- picker_type = ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE; |
- |
- if (options->type == file_system::CHOOSE_ENTRY_TYPE_OPENWRITABLEFILE && |
- !app_file_handler_util::HasFileSystemWritePermission( |
- extension_.get())) { |
- error_ = kRequiresFileSystemWriteError; |
- return false; |
- } else if (options->type == file_system::CHOOSE_ENTRY_TYPE_SAVEFILE) { |
- if (!app_file_handler_util::HasFileSystemWritePermission( |
- extension_.get())) { |
- error_ = kRequiresFileSystemWriteError; |
- return false; |
- } |
- if (multiple_) { |
- error_ = kMultipleUnsupportedError; |
- return false; |
- } |
- picker_type = ui::SelectFileDialog::SELECT_SAVEAS_FILE; |
- } else if (options->type == file_system::CHOOSE_ENTRY_TYPE_OPENDIRECTORY) { |
- is_directory_ = true; |
- if (!extension_->permissions_data()->HasAPIPermission( |
- APIPermission::kFileSystemDirectory)) { |
- error_ = kRequiresFileSystemDirectoryError; |
- return false; |
- } |
- if (multiple_) { |
- error_ = kMultipleUnsupportedError; |
- return false; |
- } |
- picker_type = ui::SelectFileDialog::SELECT_FOLDER; |
- } |
- |
- base::FilePath::StringType suggested_extension; |
- BuildSuggestion(options->suggested_name.get(), &suggested_name, |
- &suggested_extension); |
- |
- BuildFileTypeInfo(&file_type_info, suggested_extension, |
- options->accepts.get(), options->accepts_all_types.get()); |
- } |
- |
- file_type_info.allowed_paths = ui::SelectFileDialog::FileTypeInfo::ANY_PATH; |
- |
- base::FilePath previous_path = file_system_api::GetLastChooseEntryDirectory( |
- ExtensionPrefs::Get(GetProfile()), extension()->id()); |
- |
- if (previous_path.empty()) { |
- SetInitialPathAndShowPicker(previous_path, suggested_name, file_type_info, |
- picker_type, false); |
- return true; |
- } |
- |
- base::Callback<void(bool)> set_initial_path_callback = base::Bind( |
- &FileSystemChooseEntryFunction::SetInitialPathAndShowPicker, this, |
- previous_path, suggested_name, file_type_info, picker_type); |
- |
-// Check whether the |previous_path| is a non-native directory. |
#if defined(OS_CHROMEOS) |
- if (file_manager::util::IsUnderNonNativeLocalPath(GetProfile(), |
- previous_path)) { |
- file_manager::util::IsNonNativeLocalPathDirectory( |
- GetProfile(), previous_path, set_initial_path_callback); |
- return true; |
- } |
-#endif |
- base::PostTaskWithTraitsAndReplyWithResult( |
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, |
- base::Bind(&base::DirectoryExists, previous_path), |
- set_initial_path_callback); |
- |
- return true; |
+bool ChromeFileSystemDelegate::IsGrantable( |
+ content::BrowserContext* browser_context, |
+ content::RenderFrameHost* render_frame_host, |
+ const Extension& extension) { |
+ // Only kiosk apps in kiosk sessions can use this API. |
+ // Additionally it is enabled for whitelisted component extensions and apps. |
+ ConsentProviderDelegate consent_provider_delegate( |
+ Profile::FromBrowserContext(browser_context)); |
+ ConsentProvider consent_provider(&consent_provider_delegate); |
+ return consent_provider.IsGrantable(extension); |
} |
-bool FileSystemRetainEntryFunction::RunAsync() { |
- std::string entry_id; |
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id)); |
- SavedFilesService* saved_files_service = SavedFilesService::Get(GetProfile()); |
- // Add the file to the retain list if it is not already on there. |
- if (!saved_files_service->IsRegistered(extension_->id(), entry_id)) { |
- std::string filesystem_name; |
- std::string filesystem_path; |
- base::FilePath path; |
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_name)); |
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &filesystem_path)); |
- if (!app_file_handler_util::ValidateFileEntryAndGetPath( |
- filesystem_name, filesystem_path, |
- render_frame_host()->GetProcess()->GetID(), &path, &error_)) { |
- return false; |
- } |
- |
- std::string filesystem_id; |
- if (!storage::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id)) |
- return false; |
- |
- const GURL site = util::GetSiteForExtensionId(extension_id(), GetProfile()); |
- storage::FileSystemContext* const context = |
- content::BrowserContext::GetStoragePartitionForSite(GetProfile(), site) |
- ->GetFileSystemContext(); |
- const storage::FileSystemURL url = context->CreateCrackedFileSystemURL( |
- site, storage::kFileSystemTypeIsolated, |
- IsolatedContext::GetInstance() |
- ->CreateVirtualRootPath(filesystem_id) |
- .Append(base::FilePath::FromUTF8Unsafe(filesystem_path))); |
- |
- content::BrowserThread::PostTask( |
- content::BrowserThread::IO, FROM_HERE, |
- base::BindOnce( |
- base::IgnoreResult( |
- &storage::FileSystemOperationRunner::GetMetadata), |
- context->operation_runner()->AsWeakPtr(), url, |
- storage::FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY, |
- base::Bind( |
- &PassFileInfoToUIThread, |
- base::Bind(&FileSystemRetainEntryFunction::RetainFileEntry, |
- this, entry_id, path)))); |
- return true; |
- } |
- |
- saved_files_service->EnqueueFileEntry(extension_->id(), entry_id); |
- SendResponse(true); |
- return true; |
-} |
+void ChromeFileSystemDelegate::RequestFileSystem( |
+ content::BrowserContext* browser_context, |
+ scoped_refptr<UIThreadExtensionFunction> requester, |
+ const Extension& extension, |
+ std::string volume_id, |
+ bool writable, |
+ const FileSystemCallback& success_callback, |
+ const ErrorCallback& error_callback) { |
+ ConsentProviderDelegate consent_provider_delegate( |
+ Profile::FromBrowserContext(browser_context)); |
+ ConsentProvider consent_provider(&consent_provider_delegate); |
-void FileSystemRetainEntryFunction::RetainFileEntry( |
- const std::string& entry_id, |
- const base::FilePath& path, |
- std::unique_ptr<base::File::Info> file_info) { |
- if (!file_info) { |
- SendResponse(false); |
+ if (!consent_provider.IsGrantable(extension)) { |
+ error_callback.Run(kNotSupportedOnNonKioskSessionError); |
return; |
} |
- SavedFilesService* saved_files_service = SavedFilesService::Get(GetProfile()); |
- saved_files_service->RegisterFileEntry(extension_->id(), entry_id, path, |
- file_info->is_directory); |
- saved_files_service->EnqueueFileEntry(extension_->id(), entry_id); |
- SendResponse(true); |
-} |
- |
-ExtensionFunction::ResponseAction FileSystemIsRestorableFunction::Run() { |
- std::string entry_id; |
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id)); |
- return RespondNow(OneArgument(base::MakeUnique<base::Value>( |
- SavedFilesService::Get(Profile::FromBrowserContext(browser_context())) |
- ->IsRegistered(extension_->id(), entry_id)))); |
-} |
- |
-bool FileSystemRestoreEntryFunction::RunAsync() { |
- std::string entry_id; |
- bool needs_new_entry; |
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id)); |
- EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &needs_new_entry)); |
- const SavedFileEntry* file_entry = |
- SavedFilesService::Get(GetProfile()) |
- ->GetFileEntry(extension_->id(), entry_id); |
- if (!file_entry) { |
- error_ = kUnknownIdError; |
- return false; |
- } |
- |
- SavedFilesService::Get(GetProfile()) |
- ->EnqueueFileEntry(extension_->id(), entry_id); |
- |
- // Only create a new file entry if the renderer requests one. |
- // |needs_new_entry| will be false if the renderer already has an Entry for |
- // |entry_id|. |
- if (needs_new_entry) { |
- is_directory_ = file_entry->is_directory; |
- std::unique_ptr<base::DictionaryValue> result = CreateResult(); |
- AddEntryToResult(file_entry->path, file_entry->id, result.get()); |
- SetResult(std::move(result)); |
- } |
- SendResponse(true); |
- return true; |
-} |
- |
-ExtensionFunction::ResponseAction FileSystemObserveDirectoryFunction::Run() { |
- NOTIMPLEMENTED(); |
- return RespondNow(Error(kUnknownIdError)); |
-} |
- |
-ExtensionFunction::ResponseAction FileSystemUnobserveEntryFunction::Run() { |
- NOTIMPLEMENTED(); |
- return RespondNow(Error(kUnknownIdError)); |
-} |
- |
-ExtensionFunction::ResponseAction FileSystemGetObservedEntriesFunction::Run() { |
- NOTIMPLEMENTED(); |
- return RespondNow(Error(kUnknownIdError)); |
-} |
- |
-#if !defined(OS_CHROMEOS) |
-ExtensionFunction::ResponseAction FileSystemRequestFileSystemFunction::Run() { |
- using api::file_system::RequestFileSystem::Params; |
- const std::unique_ptr<Params> params(Params::Create(*args_)); |
- EXTENSION_FUNCTION_VALIDATE(params); |
- |
- NOTIMPLEMENTED(); |
- return RespondNow(Error(kNotSupportedOnCurrentPlatformError)); |
-} |
- |
-ExtensionFunction::ResponseAction FileSystemGetVolumeListFunction::Run() { |
- NOTIMPLEMENTED(); |
- return RespondNow(Error(kNotSupportedOnCurrentPlatformError)); |
-} |
-#else |
- |
-FileSystemRequestFileSystemFunction::FileSystemRequestFileSystemFunction() |
- : chrome_details_(this) {} |
- |
-FileSystemRequestFileSystemFunction::~FileSystemRequestFileSystemFunction() {} |
- |
-ExtensionFunction::ResponseAction FileSystemRequestFileSystemFunction::Run() { |
- using api::file_system::RequestFileSystem::Params; |
- const std::unique_ptr<Params> params(Params::Create(*args_)); |
- EXTENSION_FUNCTION_VALIDATE(params); |
- |
- // Only kiosk apps in kiosk sessions can use this API. |
- // Additionally it is enabled for whitelisted component extensions and apps. |
- file_system_api::ConsentProviderDelegate consent_provider_delegate( |
- chrome_details_.GetProfile(), render_frame_host()); |
- file_system_api::ConsentProvider consent_provider(&consent_provider_delegate); |
- |
- if (!consent_provider.IsGrantable(*extension())) |
- return RespondNow(Error(kNotSupportedOnNonKioskSessionError)); |
- |
using file_manager::VolumeManager; |
using file_manager::Volume; |
- VolumeManager* const volume_manager = |
- VolumeManager::Get(chrome_details_.GetProfile()); |
+ VolumeManager* const volume_manager = VolumeManager::Get(browser_context); |
DCHECK(volume_manager); |
- const bool writable = |
- params->options.writable.get() && *params->options.writable.get(); |
if (writable && |
- !app_file_handler_util::HasFileSystemWritePermission(extension_.get())) { |
- return RespondNow(Error(kRequiresFileSystemWriteError)); |
+ !app_file_handler_util::HasFileSystemWritePermission(&extension)) { |
+ error_callback.Run(kRequiresFileSystemWriteError); |
+ return; |
} |
base::WeakPtr<file_manager::Volume> volume = |
- volume_manager->FindVolumeById(params->options.volume_id); |
- if (!volume.get()) |
- return RespondNow(Error(kVolumeNotFoundError)); |
+ volume_manager->FindVolumeById(volume_id); |
+ if (!volume.get()) { |
+ error_callback.Run(kVolumeNotFoundError); |
+ return; |
+ } |
const GURL site = |
- util::GetSiteForExtensionId(extension_id(), chrome_details_.GetProfile()); |
+ util::GetSiteForExtensionId(extension.id(), browser_context); |
scoped_refptr<storage::FileSystemContext> file_system_context = |
- content::BrowserContext::GetStoragePartitionForSite( |
- chrome_details_.GetProfile(), site) |
+ content::BrowserContext::GetStoragePartitionForSite(browser_context, site) |
->GetFileSystemContext(); |
storage::ExternalFileSystemBackend* const backend = |
file_system_context->external_backend(); |
DCHECK(backend); |
base::FilePath virtual_path; |
- if (!backend->GetVirtualPath(volume->mount_path(), &virtual_path)) |
- return RespondNow(Error(kSecurityError)); |
+ if (!backend->GetVirtualPath(volume->mount_path(), &virtual_path)) { |
+ error_callback.Run(kSecurityError); |
+ return; |
+ } |
+ |
+ if (writable && (volume->is_read_only())) { |
+ error_callback.Run(kSecurityError); |
+ return; |
+ } |
- if (writable && (volume->is_read_only())) |
- return RespondNow(Error(kSecurityError)); |
+ const ConsentProvider::ConsentCallback& callback = base::Bind( |
+ &ChromeFileSystemDelegate::OnConsentReceived, base::Unretained(this), |
Devlin
2017/06/14 14:53:22
document why this unretained is safe
michaelpg
2017/06/21 00:40:07
Maybe it's not? Calling RequestConsent below may t
Devlin
2017/06/21 14:53:30
I don't know the lifetime of the dialog, but I wou
|
+ browser_context, requester, success_callback, error_callback, |
+ extension.id(), volume, writable); |
- consent_provider.RequestConsent( |
- *extension(), volume, writable, |
- base::Bind(&FileSystemRequestFileSystemFunction::OnConsentReceived, this, |
- volume, writable)); |
- return RespondLater(); |
+ consent_provider.RequestConsent(extension, requester->render_frame_host(), |
+ volume, writable, callback); |
} |
-void FileSystemRequestFileSystemFunction::OnConsentReceived( |
+void ChromeFileSystemDelegate::GetVolumeList( |
+ content::BrowserContext* browser_context, |
+ const VolumeListCallback& success_callback, |
+ const ErrorCallback& error_callback) { |
+ std::vector<file_system::Volume> result_volume_list; |
+ FillVolumeList(browser_context, &result_volume_list); |
+ |
+ success_callback.Run(result_volume_list); |
+} |
+ |
+void ChromeFileSystemDelegate::OnConsentReceived( |
+ content::BrowserContext* browser_context, |
+ scoped_refptr<UIThreadExtensionFunction> requester, |
+ const FileSystemCallback& success_callback, |
+ const ErrorCallback& error_callback, |
+ const std::string& extension_id, |
const base::WeakPtr<file_manager::Volume>& volume, |
bool writable, |
ConsentProvider::Consent result) { |
@@ -1123,18 +286,18 @@ void FileSystemRequestFileSystemFunction::OnConsentReceived( |
using file_manager::Volume; |
// Render frame host can be gone before this callback method is executed. |
- if (!render_frame_host()) { |
- Respond(Error("")); |
+ if (!requester->render_frame_host()) { |
+ error_callback.Run(""); |
Devlin
2017/06/14 14:53:22
I know this was just copied, but prefer std::strin
michaelpg
2017/06/21 00:40:07
Done.
|
return; |
} |
switch (result) { |
case ConsentProvider::CONSENT_REJECTED: |
- Respond(Error(kSecurityError)); |
+ error_callback.Run(kSecurityError); |
return; |
case ConsentProvider::CONSENT_IMPOSSIBLE: |
- Respond(Error(kConsentImpossible)); |
+ error_callback.Run(kConsentImpossible); |
return; |
case ConsentProvider::CONSENT_GRANTED: |
@@ -1142,15 +305,13 @@ void FileSystemRequestFileSystemFunction::OnConsentReceived( |
} |
if (!volume.get()) { |
- Respond(Error(kVolumeNotFoundError)); |
+ error_callback.Run(kVolumeNotFoundError); |
return; |
} |
- const GURL site = |
- util::GetSiteForExtensionId(extension_id(), chrome_details_.GetProfile()); |
+ const GURL site = util::GetSiteForExtensionId(extension_id, browser_context); |
scoped_refptr<storage::FileSystemContext> file_system_context = |
- content::BrowserContext::GetStoragePartitionForSite( |
- chrome_details_.GetProfile(), site) |
+ content::BrowserContext::GetStoragePartitionForSite(browser_context, site) |
->GetFileSystemContext(); |
storage::ExternalFileSystemBackend* const backend = |
file_system_context->external_backend(); |
@@ -1158,7 +319,7 @@ void FileSystemRequestFileSystemFunction::OnConsentReceived( |
base::FilePath virtual_path; |
if (!backend->GetVirtualPath(volume->mount_path(), &virtual_path)) { |
- Respond(Error(kSecurityError)); |
+ error_callback.Run(kSecurityError); |
return; |
} |
@@ -1169,7 +330,7 @@ void FileSystemRequestFileSystemFunction::OnConsentReceived( |
const storage::FileSystemURL original_url = |
file_system_context->CreateCrackedFileSystemURL( |
GURL(std::string(kExtensionScheme) + url::kStandardSchemeSeparator + |
- extension_id()), |
+ extension_id), |
storage::kFileSystemTypeExternal, virtual_path); |
// Set a fixed register name, as the automatic one would leak the mount point |
@@ -1181,64 +342,39 @@ void FileSystemRequestFileSystemFunction::OnConsentReceived( |
std::string() /* file_system_id */, original_url.path(), |
®ister_name); |
if (file_system_id.empty()) { |
- Respond(Error(kSecurityError)); |
+ error_callback.Run(kSecurityError); |
return; |
} |
- backend->GrantFileAccessToExtension(extension_->id(), virtual_path); |
+ backend->GrantFileAccessToExtension(extension_id, virtual_path); |
// Grant file permissions to the renderer hosting component. |
content::ChildProcessSecurityPolicy* policy = |
content::ChildProcessSecurityPolicy::GetInstance(); |
DCHECK(policy); |
+ const auto process_id = requester->render_frame_host()->GetProcess()->GetID(); |
// Read-only permisisons. |
- policy->GrantReadFile(render_frame_host()->GetProcess()->GetID(), |
- volume->mount_path()); |
- policy->GrantReadFileSystem(render_frame_host()->GetProcess()->GetID(), |
- file_system_id); |
+ policy->GrantReadFile(process_id, volume->mount_path()); |
+ policy->GrantReadFileSystem(process_id, file_system_id); |
// Additional write permissions. |
if (writable) { |
- policy->GrantCreateReadWriteFile(render_frame_host()->GetProcess()->GetID(), |
- volume->mount_path()); |
- policy->GrantCopyInto(render_frame_host()->GetProcess()->GetID(), |
- volume->mount_path()); |
- policy->GrantWriteFileSystem(render_frame_host()->GetProcess()->GetID(), |
- file_system_id); |
- policy->GrantDeleteFromFileSystem( |
- render_frame_host()->GetProcess()->GetID(), file_system_id); |
- policy->GrantCreateFileForFileSystem( |
- render_frame_host()->GetProcess()->GetID(), file_system_id); |
+ policy->GrantCreateReadWriteFile(process_id, volume->mount_path()); |
+ policy->GrantCopyInto(process_id, volume->mount_path()); |
+ policy->GrantWriteFileSystem(process_id, file_system_id); |
+ policy->GrantDeleteFromFileSystem(process_id, file_system_id); |
+ policy->GrantCreateFileForFileSystem(process_id, file_system_id); |
} |
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
- dict->SetString("file_system_id", file_system_id); |
- dict->SetString("file_system_path", register_name); |
- |
- Respond(OneArgument(std::move(dict))); |
+ success_callback.Run(file_system_id, register_name); |
} |
+#endif // defined(OS_CHROMEOS) |
-FileSystemGetVolumeListFunction::FileSystemGetVolumeListFunction() |
- : chrome_details_(this) {} |
- |
-FileSystemGetVolumeListFunction::~FileSystemGetVolumeListFunction() {} |
- |
-ExtensionFunction::ResponseAction FileSystemGetVolumeListFunction::Run() { |
- // Only kiosk apps in kiosk sessions can use this API. |
- // Additionally it is enabled for whitelisted component extensions and apps. |
- file_system_api::ConsentProviderDelegate consent_provider_delegate( |
- chrome_details_.GetProfile(), render_frame_host()); |
- file_system_api::ConsentProvider consent_provider(&consent_provider_delegate); |
- |
- if (!consent_provider.IsGrantable(*extension())) |
- return RespondNow(Error(kNotSupportedOnNonKioskSessionError)); |
- std::vector<api::file_system::Volume> result_volume_list; |
- FillVolumeList(chrome_details_.GetProfile(), &result_volume_list); |
- |
- return RespondNow(ArgumentList( |
- api::file_system::GetVolumeList::Results::Create(result_volume_list))); |
+std::unique_ptr<file_system_api::SavedFilesServiceDelegate> |
+ChromeFileSystemDelegate::CreateSavedFilesServiceDelegate( |
+ content::BrowserContext* browser_context) { |
+ return base::MakeUnique<apps::SavedFilesServiceDelegateImpl>(browser_context); |
} |
-#endif |
} // namespace extensions |