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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/file_system/file_system_api.h" 5 #include "chrome/browser/extensions/api/file_system/file_system_api.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "apps/saved_files_service.h" 9 #include "apps/saved_files_service.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 #include "ui/base/l10n/l10n_util.h" 51 #include "ui/base/l10n/l10n_util.h"
52 #include "ui/shell_dialogs/select_file_dialog.h" 52 #include "ui/shell_dialogs/select_file_dialog.h"
53 #include "ui/shell_dialogs/selected_file_info.h" 53 #include "ui/shell_dialogs/selected_file_info.h"
54 54
55 #if defined(OS_MACOSX) 55 #if defined(OS_MACOSX)
56 #include <CoreFoundation/CoreFoundation.h> 56 #include <CoreFoundation/CoreFoundation.h>
57 #include "base/mac/foundation_util.h" 57 #include "base/mac/foundation_util.h"
58 #endif 58 #endif
59 59
60 #if defined(OS_CHROMEOS) 60 #if defined(OS_CHROMEOS)
61 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
61 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h" 62 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
63 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
64 #include "components/user_manager/user_manager.h"
65 #include "extensions/common/manifest_handlers/kiosk_mode_info.h"
62 #endif 66 #endif
63 67
64 using apps::SavedFileEntry; 68 using apps::SavedFileEntry;
65 using apps::SavedFilesService; 69 using apps::SavedFilesService;
66 using storage::IsolatedContext; 70 using storage::IsolatedContext;
67 71
68 const char kInvalidCallingPage[] = "Invalid calling page. This function can't " 72 const char kInvalidCallingPage[] = "Invalid calling page. This function can't "
69 "be called from a background page."; 73 "be called from a background page.";
70 const char kUserCancelled[] = "User cancelled"; 74 const char kUserCancelled[] = "User cancelled";
71 const char kWritableFileErrorFormat[] = "Error opening %s"; 75 const char kWritableFileErrorFormat[] = "Error opening %s";
72 const char kRequiresFileSystemWriteError[] = 76 const char kRequiresFileSystemWriteError[] =
73 "Operation requires fileSystem.write permission"; 77 "Operation requires fileSystem.write permission";
74 const char kRequiresFileSystemDirectoryError[] = 78 const char kRequiresFileSystemDirectoryError[] =
75 "Operation requires fileSystem.directory permission"; 79 "Operation requires fileSystem.directory permission";
76 const char kMultipleUnsupportedError[] = 80 const char kMultipleUnsupportedError[] =
77 "acceptsMultiple: true is not supported for 'saveFile'"; 81 "acceptsMultiple: true is not supported for 'saveFile'";
78 const char kUnknownIdError[] = "Unknown id"; 82 const char kUnknownIdError[] = "Unknown id";
83 const char kVolumeNotFoundError[] = "Volume not found.";
84 const char kSecurityError[] = "Security error.";
85 const char kNotSupportedError[] = "Operation not supported.";
79 86
80 namespace file_system = extensions::api::file_system; 87 namespace file_system = extensions::api::file_system;
81 namespace ChooseEntry = file_system::ChooseEntry; 88 namespace ChooseEntry = file_system::ChooseEntry;
82 89
83 namespace { 90 namespace {
84 91
85 bool g_skip_picker_for_test = false; 92 bool g_skip_picker_for_test = false;
86 bool g_use_suggested_path_for_test = false; 93 bool g_use_suggested_path_for_test = false;
87 base::FilePath* g_path_to_be_picked_for_test; 94 base::FilePath* g_path_to_be_picked_for_test;
88 std::vector<base::FilePath>* g_paths_to_be_picked_for_test; 95 std::vector<base::FilePath>* g_paths_to_be_picked_for_test;
(...skipping 898 matching lines...) Expand 10 before | Expand all | Expand 10 after
987 error_ = kUnknownIdError; 994 error_ = kUnknownIdError;
988 return false; 995 return false;
989 } 996 }
990 997
991 bool FileSystemGetObservedEntriesFunction::RunSync() { 998 bool FileSystemGetObservedEntriesFunction::RunSync() {
992 NOTIMPLEMENTED(); 999 NOTIMPLEMENTED();
993 error_ = kUnknownIdError; 1000 error_ = kUnknownIdError;
994 return false; 1001 return false;
995 } 1002 }
996 1003
1004 FileSystemRequestFileSystemFunction::FileSystemRequestFileSystemFunction()
1005 : chrome_details_(this) {
1006 }
1007
1008 ExtensionFunction::ResponseAction FileSystemRequestFileSystemFunction::Run() {
1009 using extensions::api::file_system::RequestFileSystem::Params;
1010 const scoped_ptr<Params> params(Params::Create(*args_));
1011 EXTENSION_FUNCTION_VALIDATE(params);
1012
1013 #if !defined(OS_CHROMEOS)
1014 NOTIMPLEMENTED();
1015 return RespondNow(Error(kNotSupportedError));
1016
1017 #else
1018 using file_manager::VolumeManager;
1019 using file_manager::VolumeInfo;
1020 VolumeManager* const volume_manager =
1021 VolumeManager::Get(chrome_details_.GetProfile());
1022 DCHECK(volume_manager);
1023
1024 const bool writable =
1025 params->options.writable.get() && *params->options.writable.get();
1026 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.
1027
1028 // Only kiosk apps in kiosk sessions can use this API. Additionally component
1029 // extensions and apps, which is not documented though.
1030 if ((!user_manager::UserManager::Get()->IsLoggedInAsKioskApp() ||
1031 !KioskModeInfo::IsKioskEnabled(extension())) &&
1032 extension()->location() != Manifest::COMPONENT) {
1033 return RespondNow(Error(kNotSupportedError));
1034 }
1035
1036 if (writable &&
1037 !app_file_handler_util::HasFileSystemWritePermission(extension_.get())) {
1038 return RespondNow(Error(kRequiresFileSystemWriteError));
1039 }
1040
1041 VolumeInfo volume_info;
1042 if (!volume_manager->FindVolumeInfoById(params->options.volume_id,
1043 &volume_info)) {
1044 return RespondNow(Error(kVolumeNotFoundError));
1045 }
1046
1047 const GURL site = extensions::util::GetSiteForExtensionId(
1048 extension_id(), chrome_details_.GetProfile());
1049 scoped_refptr<storage::FileSystemContext> file_system_context =
1050 content::BrowserContext::GetStoragePartitionForSite(
1051 chrome_details_.GetProfile(), site)->GetFileSystemContext();
1052 storage::ExternalFileSystemBackend* const backend =
1053 file_system_context->external_backend();
1054 DCHECK(backend);
1055
1056 base::FilePath virtual_path;
1057 if (!backend->GetVirtualPath(volume_info.mount_path, &virtual_path))
1058 return RespondNow(Error(kSecurityError));
1059
1060 if (writable && (volume_info.is_read_only))
1061 return RespondNow(Error(kSecurityError));
1062
1063 const bool requires_consent =
1064 !chromeos::KioskAppManager::Get()->IsAutoLaunchEnabled() &&
1065 extension()->location() != Manifest::COMPONENT;
1066 if (!requires_consent) {
1067 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
1068 true); // Grant without user consent.
1069 } else {
1070 // TODO(mtomasz): Create a better display name, which is the most meaningful
1071 // to the user.
1072 const std::string display_name = !volume_info.volume_label.empty()
1073 ? volume_info.volume_label
1074 : volume_info.volume_id;
1075 RequestConsent(
1076 display_name, writable,
1077 base::Bind(&FileSystemRequestFileSystemFunction::OnConsentReceived,
1078 this, volume_info.volume_id, writable));
1079 }
1080
1081 return RespondLater();
1082 #endif
1083 }
1084
1085 void FileSystemRequestFileSystemFunction::RequestConsent(
1086 const std::string& display_name,
1087 bool writable,
1088 const base::Callback<void(bool)>& callback) {
1089 // TODO(mtomasz): Implement the consent dialog.
1090 callback.Run(false);
1091 }
1092
1093 void FileSystemRequestFileSystemFunction::OnConsentReceived(
1094 const std::string& volume_id,
1095 bool writable,
1096 bool granted) {
1097 if (!granted) {
1098 SetError(kSecurityError);
1099 return;
1100 }
1101
1102 #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.
1103 using file_manager::VolumeManager;
1104 using file_manager::VolumeInfo;
1105
1106 // Fetch the volume again, in case it's gone by the time the permission is
1107 // granted.
1108 VolumeManager* const volume_manager =
1109 VolumeManager::Get(chrome_details_.GetProfile());
1110 DCHECK(volume_manager);
1111
1112 VolumeInfo volume_info;
1113 if (!volume_manager->FindVolumeInfoById(volume_id, &volume_info)) {
1114 SetError(kVolumeNotFoundError);
1115 SendResponse(false);
1116 return;
1117 }
1118
1119 const GURL site = extensions::util::GetSiteForExtensionId(
1120 extension_id(), chrome_details_.GetProfile());
1121 scoped_refptr<storage::FileSystemContext> file_system_context =
1122 content::BrowserContext::GetStoragePartitionForSite(
1123 chrome_details_.GetProfile(), site)->GetFileSystemContext();
1124 storage::ExternalFileSystemBackend* const backend =
1125 file_system_context->external_backend();
1126 DCHECK(backend);
1127
1128 // The volume may be unmounted and remounted by the time we reach this logic.
1129 // TODO(mtomasz): Add a unique identifier to VolumeInfo to guarantee that the
1130 // permissions are granted to exactly that volume which was plugged in when
1131 // the dialog was shown.
1132 base::FilePath virtual_path;
1133 if (!backend->GetVirtualPath(volume_info.mount_path, &virtual_path)) {
1134 SetError(kSecurityError);
1135 SendResponse(false);
1136 return;
1137 }
1138
1139 storage::IsolatedContext* const isolated_context =
1140 storage::IsolatedContext::GetInstance();
1141 DCHECK(isolated_context);
1142
1143 const storage::FileSystemURL original_url =
1144 file_system_context->CreateCrackedFileSystemURL(
1145 GURL("chrome-extension://" + extension_id()),
1146 storage::kFileSystemTypeExternal, virtual_path);
1147
1148 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
1149 const std::string file_system_id =
1150 isolated_context->RegisterFileSystemForPath(
1151 storage::kFileSystemTypeNativeForPlatformApp,
1152 std::string() /* file_system_id */, original_url.path(),
1153 &register_name);
1154 if (file_system_id.empty()) {
1155 SetError(kSecurityError);
1156 SendResponse(false);
1157 return;
1158 }
1159
1160 backend->GrantFileAccessToExtension(extension_->id(), virtual_path);
1161
1162 // Grant file permissions to the renderer hosting component.
1163 content::ChildProcessSecurityPolicy* policy =
1164 content::ChildProcessSecurityPolicy::GetInstance();
1165 DCHECK(policy);
1166
1167 // Read-only permisisons.
1168 policy->GrantReadFile(render_view_host()->GetProcess()->GetID(),
1169 volume_info.mount_path);
1170 policy->GrantReadFileSystem(render_view_host()->GetProcess()->GetID(),
1171 file_system_id);
1172
1173 // Additional write permissions.
1174 if (writable) {
1175 policy->GrantCreateReadWriteFile(render_view_host()->GetProcess()->GetID(),
1176 volume_info.mount_path);
1177 policy->GrantCopyInto(render_view_host()->GetProcess()->GetID(),
1178 volume_info.mount_path);
1179 policy->GrantWriteFileSystem(render_view_host()->GetProcess()->GetID(),
1180 file_system_id);
1181 policy->GrantDeleteFromFileSystem(render_view_host()->GetProcess()->GetID(),
1182 file_system_id);
1183 policy->GrantCreateFileForFileSystem(
1184 render_view_host()->GetProcess()->GetID(), file_system_id);
1185 }
1186
1187 base::DictionaryValue* const dict = new base::DictionaryValue();
1188 dict->SetString("file_system_id", file_system_id);
1189 dict->SetString("file_system_path", register_name);
1190
1191 SetResult(dict);
1192 SendResponse(true);
1193 #endif
1194 }
1195
997 } // namespace extensions 1196 } // namespace extensions
OLDNEW
« 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