Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6044)

Unified Diff: chrome/browser/extensions/api/file_system/file_system_api.cc

Issue 985533004: Implement chrome.fileSystem.requestFileSystem(). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Cleaned up. Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/api/file_system/file_system_api.cc
diff --git a/chrome/browser/extensions/api/file_system/file_system_api.cc b/chrome/browser/extensions/api/file_system/file_system_api.cc
index dbe8bfdc83aa506e9c2dc6cabb020662319e8094..723060f44088ae64c50ebcca6f87498563419cd0 100644
--- a/chrome/browser/extensions/api/file_system/file_system_api.cc
+++ b/chrome/browser/extensions/api/file_system/file_system_api.cc
@@ -58,7 +58,11 @@
#endif
#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
#include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
+#include "chrome/browser/chromeos/file_manager/volume_manager.h"
+#include "components/user_manager/user_manager.h"
+#include "extensions/common/manifest_handlers/kiosk_mode_info.h"
#endif
using apps::SavedFileEntry;
@@ -76,6 +80,9 @@ const char kRequiresFileSystemDirectoryError[] =
const char kMultipleUnsupportedError[] =
"acceptsMultiple: true is not supported for 'saveFile'";
const char kUnknownIdError[] = "Unknown id";
+const char kVolumeNotFoundError[] = "Volume not found.";
+const char kSecurityError[] = "Security error.";
+const char kNotSupportedError[] = "Operation not supported.";
namespace file_system = extensions::api::file_system;
namespace ChooseEntry = file_system::ChooseEntry;
@@ -994,4 +1001,196 @@ bool FileSystemGetObservedEntriesFunction::RunSync() {
return false;
}
+FileSystemRequestFileSystemFunction::FileSystemRequestFileSystemFunction()
+ : chrome_details_(this) {
+}
+
+ExtensionFunction::ResponseAction FileSystemRequestFileSystemFunction::Run() {
+ using extensions::api::file_system::RequestFileSystem::Params;
+ const scoped_ptr<Params> params(Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+#if !defined(OS_CHROMEOS)
+ NOTIMPLEMENTED();
+ return RespondNow(Error(kNotSupportedError));
+
+#else
+ using file_manager::VolumeManager;
+ using file_manager::VolumeInfo;
+ VolumeManager* const volume_manager =
+ VolumeManager::Get(chrome_details_.GetProfile());
+ DCHECK(volume_manager);
+
+ const bool writable =
+ params->options.writable.get() && *params->options.writable.get();
+ LOG(ERROR) << params->options.volume_id << ": " << writable;
hirono 2015/03/18 03:41:05 nit: Debug log.
mtomasz 2015/03/19 01:17:20 Done.
+
+ // Only kiosk apps in kiosk sessions can use this API. Additionally component
+ // extensions and apps, which is not documented though.
+ if ((!user_manager::UserManager::Get()->IsLoggedInAsKioskApp() ||
+ !KioskModeInfo::IsKioskEnabled(extension())) &&
+ extension()->location() != Manifest::COMPONENT) {
+ return RespondNow(Error(kNotSupportedError));
+ }
+
+ if (writable &&
+ !app_file_handler_util::HasFileSystemWritePermission(extension_.get())) {
+ return RespondNow(Error(kRequiresFileSystemWriteError));
+ }
+
+ VolumeInfo volume_info;
+ if (!volume_manager->FindVolumeInfoById(params->options.volume_id,
+ &volume_info)) {
+ return RespondNow(Error(kVolumeNotFoundError));
+ }
+
+ const GURL site = extensions::util::GetSiteForExtensionId(
+ extension_id(), chrome_details_.GetProfile());
+ scoped_refptr<storage::FileSystemContext> file_system_context =
+ content::BrowserContext::GetStoragePartitionForSite(
+ chrome_details_.GetProfile(), site)->GetFileSystemContext();
+ storage::ExternalFileSystemBackend* const backend =
+ file_system_context->external_backend();
+ DCHECK(backend);
+
+ base::FilePath virtual_path;
+ if (!backend->GetVirtualPath(volume_info.mount_path, &virtual_path))
+ return RespondNow(Error(kSecurityError));
+
+ if (writable && (volume_info.is_read_only))
+ return RespondNow(Error(kSecurityError));
+
+ const bool requires_consent =
+ !chromeos::KioskAppManager::Get()->IsAutoLaunchEnabled() &&
+ extension()->location() != Manifest::COMPONENT;
+ if (!requires_consent) {
+ OnConsentReceived(volume_info.volume_id, writable,
hirono 2015/03/18 03:41:05 Just confirmation, if OnConsentRecived called dire
mtomasz 2015/03/19 01:17:20 Good catch. It works as RespondLater() simply retu
+ true); // Grant without user consent.
+ } else {
+ // TODO(mtomasz): Create a better display name, which is the most meaningful
+ // to the user.
+ const std::string display_name = !volume_info.volume_label.empty()
+ ? volume_info.volume_label
+ : volume_info.volume_id;
+ RequestConsent(
+ display_name, writable,
+ base::Bind(&FileSystemRequestFileSystemFunction::OnConsentReceived,
+ this, volume_info.volume_id, writable));
+ }
+
+ return RespondLater();
+#endif
+}
+
+void FileSystemRequestFileSystemFunction::RequestConsent(
+ const std::string& display_name,
+ bool writable,
+ const base::Callback<void(bool)>& callback) {
+ // TODO(mtomasz): Implement the consent dialog.
+ callback.Run(false);
+}
+
+void FileSystemRequestFileSystemFunction::OnConsentReceived(
+ const std::string& volume_id,
+ bool writable,
+ bool granted) {
+ if (!granted) {
+ SetError(kSecurityError);
+ return;
+ }
+
+#if defined(OS_CHROMEOS)
hirono 2015/03/18 03:41:05 How about enclosing entire RequsetContext and OnCo
mtomasz 2015/03/19 01:17:20 Done.
+ using file_manager::VolumeManager;
+ using file_manager::VolumeInfo;
+
+ // Fetch the volume again, in case it's gone by the time the permission is
+ // granted.
+ VolumeManager* const volume_manager =
+ VolumeManager::Get(chrome_details_.GetProfile());
+ DCHECK(volume_manager);
+
+ VolumeInfo volume_info;
+ if (!volume_manager->FindVolumeInfoById(volume_id, &volume_info)) {
+ SetError(kVolumeNotFoundError);
+ SendResponse(false);
+ return;
+ }
+
+ const GURL site = extensions::util::GetSiteForExtensionId(
+ extension_id(), chrome_details_.GetProfile());
+ scoped_refptr<storage::FileSystemContext> file_system_context =
+ content::BrowserContext::GetStoragePartitionForSite(
+ chrome_details_.GetProfile(), site)->GetFileSystemContext();
+ storage::ExternalFileSystemBackend* const backend =
+ file_system_context->external_backend();
+ DCHECK(backend);
+
+ // The volume may be unmounted and remounted by the time we reach this logic.
+ // TODO(mtomasz): Add a unique identifier to VolumeInfo to guarantee that the
+ // permissions are granted to exactly that volume which was plugged in when
+ // the dialog was shown.
+ base::FilePath virtual_path;
+ if (!backend->GetVirtualPath(volume_info.mount_path, &virtual_path)) {
+ SetError(kSecurityError);
+ SendResponse(false);
+ return;
+ }
+
+ storage::IsolatedContext* const isolated_context =
+ storage::IsolatedContext::GetInstance();
+ DCHECK(isolated_context);
+
+ const storage::FileSystemURL original_url =
+ file_system_context->CreateCrackedFileSystemURL(
+ GURL("chrome-extension://" + extension_id()),
+ storage::kFileSystemTypeExternal, virtual_path);
+
+ std::string register_name = "fs";
hirono 2015/03/18 03:41:05 Do we need to assign "fs"?
mtomasz 2015/03/19 01:17:20 Without it we would leak the mount point path, we
+ const std::string file_system_id =
+ isolated_context->RegisterFileSystemForPath(
+ storage::kFileSystemTypeNativeForPlatformApp,
+ std::string() /* file_system_id */, original_url.path(),
+ &register_name);
+ if (file_system_id.empty()) {
+ SetError(kSecurityError);
+ SendResponse(false);
+ return;
+ }
+
+ backend->GrantFileAccessToExtension(extension_->id(), virtual_path);
+
+ // Grant file permissions to the renderer hosting component.
+ content::ChildProcessSecurityPolicy* policy =
+ content::ChildProcessSecurityPolicy::GetInstance();
+ DCHECK(policy);
+
+ // Read-only permisisons.
+ policy->GrantReadFile(render_view_host()->GetProcess()->GetID(),
+ volume_info.mount_path);
+ policy->GrantReadFileSystem(render_view_host()->GetProcess()->GetID(),
+ file_system_id);
+
+ // Additional write permissions.
+ if (writable) {
+ policy->GrantCreateReadWriteFile(render_view_host()->GetProcess()->GetID(),
+ volume_info.mount_path);
+ policy->GrantCopyInto(render_view_host()->GetProcess()->GetID(),
+ volume_info.mount_path);
+ policy->GrantWriteFileSystem(render_view_host()->GetProcess()->GetID(),
+ file_system_id);
+ policy->GrantDeleteFromFileSystem(render_view_host()->GetProcess()->GetID(),
+ file_system_id);
+ policy->GrantCreateFileForFileSystem(
+ render_view_host()->GetProcess()->GetID(), file_system_id);
+ }
+
+ base::DictionaryValue* const dict = new base::DictionaryValue();
+ dict->SetString("file_system_id", file_system_id);
+ dict->SetString("file_system_path", register_name);
+
+ SetResult(dict);
+ SendResponse(true);
+#endif
+}
+
} // namespace extensions
« no previous file with comments | « chrome/browser/extensions/api/file_system/file_system_api.h ('k') | chrome/common/extensions/api/_permission_features.json » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698