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

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: Fixed kiosk mode. 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 "base/thread_task_runner_handle.h"
62 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
61 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h" 63 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
64 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
65 #include "components/user_manager/user_manager.h"
66 #include "extensions/common/constants.h"
67 #include "extensions/common/manifest_handlers/kiosk_mode_info.h"
68 #include "url/url_constants.h"
62 #endif 69 #endif
63 70
64 using apps::SavedFileEntry; 71 using apps::SavedFileEntry;
65 using apps::SavedFilesService; 72 using apps::SavedFilesService;
66 using storage::IsolatedContext; 73 using storage::IsolatedContext;
67 74
68 const char kInvalidCallingPage[] = "Invalid calling page. This function can't " 75 const char kInvalidCallingPage[] = "Invalid calling page. This function can't "
69 "be called from a background page."; 76 "be called from a background page.";
70 const char kUserCancelled[] = "User cancelled"; 77 const char kUserCancelled[] = "User cancelled";
71 const char kWritableFileErrorFormat[] = "Error opening %s"; 78 const char kWritableFileErrorFormat[] = "Error opening %s";
72 const char kRequiresFileSystemWriteError[] = 79 const char kRequiresFileSystemWriteError[] =
73 "Operation requires fileSystem.write permission"; 80 "Operation requires fileSystem.write permission";
74 const char kRequiresFileSystemDirectoryError[] = 81 const char kRequiresFileSystemDirectoryError[] =
75 "Operation requires fileSystem.directory permission"; 82 "Operation requires fileSystem.directory permission";
76 const char kMultipleUnsupportedError[] = 83 const char kMultipleUnsupportedError[] =
77 "acceptsMultiple: true is not supported for 'saveFile'"; 84 "acceptsMultiple: true is not supported for 'saveFile'";
78 const char kUnknownIdError[] = "Unknown id"; 85 const char kUnknownIdError[] = "Unknown id";
79 86
87 #if !defined(OS_CHROMEOS)
88 const char kNotSupportedOnCurrentPlatformError[] =
89 "Operation not supported on the current platform.";
90 #else
91 const char kNotSupportedOnNonKioskSessionError[] =
92 "Operation only supported for kiosk apps running in a kiosk session.";
93 const char kVolumeNotFoundError[] = "Volume not found.";
94 const char kSecurityError[] = "Security error.";
95 #endif
96
80 namespace file_system = extensions::api::file_system; 97 namespace file_system = extensions::api::file_system;
81 namespace ChooseEntry = file_system::ChooseEntry; 98 namespace ChooseEntry = file_system::ChooseEntry;
82 99
83 namespace { 100 namespace {
84 101
85 bool g_skip_picker_for_test = false; 102 bool g_skip_picker_for_test = false;
86 bool g_use_suggested_path_for_test = false; 103 bool g_use_suggested_path_for_test = false;
87 base::FilePath* g_path_to_be_picked_for_test; 104 base::FilePath* g_path_to_be_picked_for_test;
88 std::vector<base::FilePath>* g_paths_to_be_picked_for_test; 105 std::vector<base::FilePath>* g_paths_to_be_picked_for_test;
89 bool g_skip_directory_confirmation_for_test = false; 106 bool g_skip_directory_confirmation_for_test = false;
(...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after
987 error_ = kUnknownIdError; 1004 error_ = kUnknownIdError;
988 return false; 1005 return false;
989 } 1006 }
990 1007
991 bool FileSystemGetObservedEntriesFunction::RunSync() { 1008 bool FileSystemGetObservedEntriesFunction::RunSync() {
992 NOTIMPLEMENTED(); 1009 NOTIMPLEMENTED();
993 error_ = kUnknownIdError; 1010 error_ = kUnknownIdError;
994 return false; 1011 return false;
995 } 1012 }
996 1013
1014 FileSystemRequestFileSystemFunction::FileSystemRequestFileSystemFunction()
1015 : chrome_details_(this) {
1016 }
1017
1018 ExtensionFunction::ResponseAction FileSystemRequestFileSystemFunction::Run() {
1019 using extensions::api::file_system::RequestFileSystem::Params;
1020 const scoped_ptr<Params> params(Params::Create(*args_));
1021 EXTENSION_FUNCTION_VALIDATE(params);
1022
1023 #if !defined(OS_CHROMEOS)
1024 NOTIMPLEMENTED();
1025 return RespondNow(Error(kNotSupportedOnCurrentPlatformError));
1026
1027 #else
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(kNotSupportedOnNonKioskSessionError));
1034 }
1035
1036 using file_manager::VolumeManager;
1037 using file_manager::VolumeInfo;
1038 VolumeManager* const volume_manager =
1039 VolumeManager::Get(chrome_details_.GetProfile());
1040 DCHECK(volume_manager);
1041
1042 const bool writable =
1043 params->options.writable.get() && *params->options.writable.get();
1044 if (writable &&
1045 !app_file_handler_util::HasFileSystemWritePermission(extension_.get())) {
1046 return RespondNow(Error(kRequiresFileSystemWriteError));
1047 }
1048
1049 VolumeInfo volume_info;
1050 if (!volume_manager->FindVolumeInfoById(params->options.volume_id,
1051 &volume_info)) {
1052 return RespondNow(Error(kVolumeNotFoundError));
1053 }
1054
1055 const GURL site = extensions::util::GetSiteForExtensionId(
1056 extension_id(), chrome_details_.GetProfile());
1057 scoped_refptr<storage::FileSystemContext> file_system_context =
1058 content::BrowserContext::GetStoragePartitionForSite(
1059 chrome_details_.GetProfile(), site)->GetFileSystemContext();
1060 storage::ExternalFileSystemBackend* const backend =
1061 file_system_context->external_backend();
1062 DCHECK(backend);
1063
1064 base::FilePath virtual_path;
1065 if (!backend->GetVirtualPath(volume_info.mount_path, &virtual_path))
1066 return RespondNow(Error(kSecurityError));
1067
1068 if (writable && (volume_info.is_read_only))
1069 return RespondNow(Error(kSecurityError));
1070
1071 chromeos::KioskAppManager::App app_info;
1072 chromeos::KioskAppManager::Get()->GetApp(extension_id(), &app_info);
1073 const bool is_auto_launched = app_info.was_auto_launched_with_zero_delay;
1074 const bool requires_consent =
1075 !is_auto_launched && extension()->location() != Manifest::COMPONENT;
1076
1077 if (!requires_consent) {
1078 // Grant the permission without showing the dialog.
1079 base::ThreadTaskRunnerHandle::Get()->PostTask(
1080 FROM_HERE,
1081 base::Bind(&FileSystemRequestFileSystemFunction::OnConsentReceived,
1082 this, volume_info.volume_id, writable, true /* granted */));
1083 } else {
1084 // TODO(mtomasz): Create a better display name, which is the most meaningful
1085 // to the user.
1086 const std::string display_name = !volume_info.volume_label.empty()
1087 ? volume_info.volume_label
1088 : volume_info.volume_id;
1089 RequestConsent(
1090 display_name, writable,
1091 base::Bind(&FileSystemRequestFileSystemFunction::OnConsentReceived,
1092 this, volume_info.volume_id, writable));
1093 }
1094
1095 return RespondLater();
1096 #endif
1097 }
1098
1099 #if defined(OS_CHROMEOS)
1100 void FileSystemRequestFileSystemFunction::RequestConsent(
1101 const std::string& display_name,
1102 bool writable,
1103 const base::Callback<void(bool)>& callback) {
1104 // TODO(mtomasz): Implement the consent dialog.
1105 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1106 base::Bind(callback, false));
1107 }
1108
1109 void FileSystemRequestFileSystemFunction::OnConsentReceived(
1110 const std::string& volume_id,
1111 bool writable,
1112 bool granted) {
1113 using file_manager::VolumeManager;
1114 using file_manager::VolumeInfo;
1115
1116 if (!granted) {
1117 SetError(kSecurityError);
1118 SendResponse(false);
1119 return;
1120 }
1121
1122 // The volume may be unmounted and remounted by the time we reach this logic.
1123 // As for now, fetch the volume again, in case it's gone by the time the
1124 // permission is granted.
1125 // TODO(mtomasz): Add a unique identifier to VolumeInfo to guarantee that the
1126 // permissions are granted to exactly that volume which was plugged in when
1127 // the dialog was shown.
1128 VolumeManager* const volume_manager =
1129 VolumeManager::Get(chrome_details_.GetProfile());
1130 DCHECK(volume_manager);
1131
1132 VolumeInfo volume_info;
1133 if (!volume_manager->FindVolumeInfoById(volume_id, &volume_info)) {
1134 SetError(kVolumeNotFoundError);
1135 SendResponse(false);
1136 return;
1137 }
1138
1139 const GURL site = extensions::util::GetSiteForExtensionId(
1140 extension_id(), chrome_details_.GetProfile());
1141 scoped_refptr<storage::FileSystemContext> file_system_context =
1142 content::BrowserContext::GetStoragePartitionForSite(
1143 chrome_details_.GetProfile(), site)->GetFileSystemContext();
1144 storage::ExternalFileSystemBackend* const backend =
1145 file_system_context->external_backend();
1146 DCHECK(backend);
1147
1148 base::FilePath virtual_path;
1149 if (!backend->GetVirtualPath(volume_info.mount_path, &virtual_path)) {
1150 SetError(kSecurityError);
1151 SendResponse(false);
1152 return;
1153 }
1154
1155 storage::IsolatedContext* const isolated_context =
1156 storage::IsolatedContext::GetInstance();
1157 DCHECK(isolated_context);
1158
1159 const storage::FileSystemURL original_url =
1160 file_system_context->CreateCrackedFileSystemURL(
1161 GURL(std::string(extensions::kExtensionScheme) +
1162 url::kStandardSchemeSeparator + extension_id()),
1163 storage::kFileSystemTypeExternal, virtual_path);
1164
1165 // Set a fixed register name, as the automatic one would leak the mount point
1166 // directory.
1167 std::string register_name = "fs";
1168 const std::string file_system_id =
1169 isolated_context->RegisterFileSystemForPath(
1170 storage::kFileSystemTypeNativeForPlatformApp,
1171 std::string() /* file_system_id */, original_url.path(),
1172 &register_name);
1173 if (file_system_id.empty()) {
1174 SetError(kSecurityError);
1175 SendResponse(false);
1176 return;
1177 }
1178
1179 backend->GrantFileAccessToExtension(extension_->id(), virtual_path);
1180
1181 // Grant file permissions to the renderer hosting component.
1182 content::ChildProcessSecurityPolicy* policy =
1183 content::ChildProcessSecurityPolicy::GetInstance();
1184 DCHECK(policy);
1185
1186 // Read-only permisisons.
1187 policy->GrantReadFile(render_view_host()->GetProcess()->GetID(),
1188 volume_info.mount_path);
1189 policy->GrantReadFileSystem(render_view_host()->GetProcess()->GetID(),
1190 file_system_id);
1191
1192 // Additional write permissions.
1193 if (writable) {
1194 policy->GrantCreateReadWriteFile(render_view_host()->GetProcess()->GetID(),
1195 volume_info.mount_path);
1196 policy->GrantCopyInto(render_view_host()->GetProcess()->GetID(),
1197 volume_info.mount_path);
1198 policy->GrantWriteFileSystem(render_view_host()->GetProcess()->GetID(),
1199 file_system_id);
1200 policy->GrantDeleteFromFileSystem(render_view_host()->GetProcess()->GetID(),
1201 file_system_id);
1202 policy->GrantCreateFileForFileSystem(
1203 render_view_host()->GetProcess()->GetID(), file_system_id);
1204 }
1205
1206 base::DictionaryValue* const dict = new base::DictionaryValue();
1207 dict->SetString("file_system_id", file_system_id);
1208 dict->SetString("file_system_path", register_name);
1209
1210 SetResult(dict);
1211 SendResponse(true);
1212 }
1213 #endif
1214
997 } // namespace extensions 1215 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698