Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/devtools/devtools_file_system_helper.h" | |
| 6 | |
| 7 #include <vector> | |
| 8 | |
| 9 #include "base/bind.h" | |
| 10 #include "base/file_util.h" | |
| 11 #include "base/utf_string_conversions.h" | |
| 12 #include "chrome/browser/prefs/pref_service.h" | |
| 13 #include "chrome/browser/prefs/scoped_user_pref_update.h" | |
| 14 #include "chrome/browser/profiles/profile.h" | |
| 15 #include "chrome/browser/ui/chrome_select_file_policy.h" | |
| 16 #include "chrome/common/pref_names.h" | |
| 17 #include "content/public/browser/browser_thread.h" | |
| 18 #include "content/public/browser/child_process_security_policy.h" | |
| 19 #include "content/public/browser/render_process_host.h" | |
| 20 #include "content/public/browser/render_view_host.h" | |
| 21 #include "content/public/browser/web_contents.h" | |
| 22 #include "grit/generated_resources.h" | |
| 23 #include "ui/base/dialogs/select_file_dialog.h" | |
| 24 #include "ui/base/l10n/l10n_util.h" | |
| 25 #include "webkit/fileapi/isolated_context.h" | |
| 26 | |
| 27 using content::BrowserThread; | |
| 28 using content::RenderViewHost; | |
| 29 using content::WebContents; | |
| 30 | |
| 31 namespace { | |
| 32 const char kSecurityFileName[] = ".allow-devtools-edit"; | |
| 33 } | |
| 34 | |
| 35 class DevToolsFileSystemHelper::SelectFolderDialog | |
|
pfeldman
2012/12/24 19:01:03
This class is almost exactly the same as the one i
| |
| 36 : public ui::SelectFileDialog::Listener, | |
| 37 public base::RefCounted<SelectFolderDialog> { | |
| 38 public: | |
| 39 explicit SelectFolderDialog(DevToolsFileSystemHelper* helper) | |
| 40 : helper_(helper) { | |
| 41 select_file_dialog_ = ui::SelectFileDialog::Create( | |
| 42 this, new ChromeSelectFilePolicy(NULL)); | |
| 43 } | |
| 44 | |
| 45 void ResetHelper() { | |
| 46 helper_ = NULL; | |
| 47 } | |
| 48 | |
| 49 void Show() { | |
| 50 AddRef(); // Balanced in the three listener outcomes. | |
| 51 select_file_dialog_->SelectFile(ui::SelectFileDialog::SELECT_FOLDER, | |
| 52 string16(), | |
| 53 FilePath(), | |
| 54 NULL, | |
| 55 0, | |
| 56 FILE_PATH_LITERAL(""), | |
| 57 NULL, | |
| 58 NULL); | |
| 59 } | |
| 60 | |
| 61 // ui::SelectFileDialog::Listener implementation. | |
| 62 virtual void FileSelected(const FilePath& path, | |
| 63 int index, void* params) { | |
| 64 if (helper_) | |
| 65 helper_->FolderSelected(path); | |
| 66 Release(); // Balanced in ::Show. | |
| 67 } | |
| 68 | |
| 69 virtual void MultiFilesSelected( | |
| 70 const std::vector<FilePath>& files, void* params) { | |
| 71 Release(); // Balanced in ::Show. | |
| 72 NOTREACHED() << "Should not be able to select multiple files"; | |
| 73 } | |
| 74 | |
| 75 virtual void FileSelectionCanceled(void* params) { | |
| 76 if (helper_) | |
| 77 helper_->FolderSelectionCanceled(); | |
| 78 Release(); // Balanced in ::Show. | |
| 79 } | |
| 80 | |
| 81 private: | |
| 82 friend class base::RefCounted<SelectFolderDialog>; | |
| 83 virtual ~SelectFolderDialog() {} | |
| 84 | |
| 85 scoped_refptr<ui::SelectFileDialog> select_file_dialog_; | |
| 86 DevToolsFileSystemHelper* helper_; | |
| 87 }; | |
| 88 | |
| 89 DevToolsFileSystemHelper::FileSystem::FileSystem( | |
| 90 const std::string& filesystem_id, | |
| 91 const std::string& registered_name, | |
| 92 const std::string& file_system_path) | |
| 93 : filesystem_id(filesystem_id), | |
| 94 registered_name(registered_name), | |
| 95 file_system_path(file_system_path) { | |
| 96 } | |
| 97 | |
| 98 DevToolsFileSystemHelper::DevToolsFileSystemHelper( | |
| 99 WebContents* web_contents, | |
| 100 Profile* profile, | |
| 101 Delegate* delegate) | |
| 102 : web_contents_(web_contents), | |
| 103 profile_(profile), | |
| 104 delegate_(delegate) { | |
| 105 } | |
| 106 | |
| 107 DevToolsFileSystemHelper::~DevToolsFileSystemHelper() { | |
| 108 if (select_folder_dialog_) | |
| 109 select_folder_dialog_->ResetHelper(); | |
| 110 } | |
| 111 | |
| 112 namespace { | |
| 113 | |
| 114 fileapi::IsolatedContext* isolated_context() { | |
| 115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 116 fileapi::IsolatedContext* isolated_context = | |
| 117 fileapi::IsolatedContext::GetInstance(); | |
| 118 DCHECK(isolated_context); | |
| 119 return isolated_context; | |
| 120 } | |
| 121 | |
| 122 std::string RegisterFileSystem(WebContents* web_contents, | |
| 123 const FilePath& path, | |
| 124 std::string* registered_name) { | |
| 125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 126 std::string file_system_id = isolated_context()->RegisterFileSystemForPath( | |
| 127 fileapi::kFileSystemTypeNativeLocal, path, registered_name); | |
| 128 | |
| 129 content::ChildProcessSecurityPolicy* policy = | |
| 130 content::ChildProcessSecurityPolicy::GetInstance(); | |
| 131 RenderViewHost* render_view_host = web_contents->GetRenderViewHost(); | |
| 132 int renderer_id = render_view_host->GetProcess()->GetID(); | |
| 133 policy->GrantReadWriteFileSystem(renderer_id, file_system_id); | |
| 134 | |
| 135 // We only need file level access for reading FileEntries. Saving FileEntries | |
| 136 // just needs the file system to have read/write access, which is granted | |
| 137 // above if required. | |
| 138 if (!policy->CanReadFile(renderer_id, path)) | |
| 139 policy->GrantReadFile(renderer_id, path); | |
| 140 | |
| 141 return file_system_id; | |
| 142 } | |
| 143 | |
| 144 bool CheckSecurityFileExistsInFolder(const FilePath& path) { | |
| 145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 146 FilePath security_file_path = path.Append( | |
| 147 FILE_PATH_LITERAL(kSecurityFileName)); | |
| 148 return file_util::PathExists(security_file_path); | |
| 149 } | |
| 150 | |
| 151 } // namespace | |
| 152 | |
| 153 void DevToolsFileSystemHelper::SelectFolderAndGrantPermission() { | |
| 154 if (select_folder_dialog_) | |
| 155 select_folder_dialog_->ResetHelper(); | |
| 156 select_folder_dialog_ = new SelectFolderDialog(this); | |
| 157 select_folder_dialog_->Show(); | |
| 158 } | |
| 159 | |
| 160 void DevToolsFileSystemHelper::FolderSelected(const FilePath& path) { | |
| 161 BrowserThread::PostTask( | |
| 162 BrowserThread::FILE, FROM_HERE, | |
| 163 base::Bind(&DevToolsFileSystemHelper::CheckSelectedPath, this, path)); | |
| 164 } | |
| 165 | |
| 166 void DevToolsFileSystemHelper::FolderSelectionCanceled() { | |
| 167 delegate_->FileSystemFolderSelectionCanceled(); | |
| 168 } | |
| 169 | |
| 170 void DevToolsFileSystemHelper::CheckSelectedPath(const FilePath& path) { | |
| 171 if (!CheckSecurityFileExistsInFolder(path)) { | |
| 172 BrowserThread::PostTask( | |
| 173 BrowserThread::UI, FROM_HERE, | |
| 174 base::Bind(&DevToolsFileSystemHelper::SelectedFileSystemForbidden, | |
| 175 this)); | |
| 176 return; | |
| 177 } | |
| 178 | |
| 179 BrowserThread::PostTask( | |
| 180 BrowserThread::UI, FROM_HERE, | |
| 181 base::Bind(&DevToolsFileSystemHelper::SelectedFileSystemPermitted, | |
| 182 this, | |
| 183 path)); | |
| 184 } | |
| 185 | |
| 186 void DevToolsFileSystemHelper::SelectedFileSystemPermitted( | |
| 187 const FilePath& path) { | |
| 188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 189 std::string registered_name; | |
| 190 std::string file_system_id = RegisterFileSystem(web_contents_, | |
| 191 path, | |
| 192 ®istered_name); | |
| 193 std::string file_system_path = path.AsUTF8Unsafe(); | |
| 194 | |
| 195 DictionaryPrefUpdate update(profile_->GetPrefs(), | |
| 196 prefs::kDevToolsSavedFileSystemPathes); | |
| 197 DictionaryValue* file_systems_pathes_value = update.Get(); | |
| 198 file_systems_pathes_value->Set(file_system_path, Value::CreateNullValue()); | |
| 199 | |
| 200 FileSystem file_system(file_system_id, registered_name, file_system_path); | |
| 201 delegate_->FileSystemFolderSelected(file_system); | |
| 202 } | |
| 203 | |
| 204 void DevToolsFileSystemHelper::SelectedFileSystemForbidden() { | |
| 205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 206 std::string error_string = l10n_util::GetStringFUTF8( | |
| 207 IDS_DEV_TOOLS_FILE_SYSTEM_SECURITY_FILE_NOT_EXISTS_MESSAGE, | |
| 208 UTF8ToUTF16(kSecurityFileName)); | |
| 209 delegate_->FileSystemFolderSelectionError(error_string); | |
| 210 } | |
| 211 | |
| 212 void DevToolsFileSystemHelper::RequestPermissions() { | |
| 213 const DictionaryValue* file_systems_pathes_value = | |
| 214 profile_->GetPrefs()->GetDictionary( | |
| 215 prefs::kDevToolsSavedFileSystemPathes); | |
| 216 std::vector<FilePath> saved_pathes; | |
| 217 DictionaryValue::key_iterator it = file_systems_pathes_value->begin_keys(); | |
| 218 for (; it != file_systems_pathes_value->end_keys(); ++it) { | |
| 219 std::string file_system_path = *it; | |
| 220 FilePath path = FilePath::FromUTF8Unsafe(file_system_path); | |
| 221 saved_pathes.push_back(path); | |
| 222 } | |
| 223 | |
| 224 BrowserThread::PostTask( | |
| 225 BrowserThread::FILE, FROM_HERE, | |
| 226 base::Bind(&DevToolsFileSystemHelper::CheckSavedPathes, | |
| 227 this, | |
| 228 saved_pathes)); | |
| 229 } | |
| 230 | |
| 231 void DevToolsFileSystemHelper::CheckSavedPathes( | |
| 232 const std::vector<FilePath>& file_pathes) { | |
| 233 std::vector<FilePath> permitted_pathes; | |
| 234 std::vector<FilePath>::const_iterator it; | |
| 235 for (it = file_pathes.begin(); it != file_pathes.end(); ++it) { | |
| 236 if (CheckSecurityFileExistsInFolder(*it)) | |
| 237 permitted_pathes.push_back(*it); | |
| 238 } | |
| 239 | |
| 240 BrowserThread::PostTask( | |
| 241 BrowserThread::UI, FROM_HERE, | |
| 242 base::Bind(&DevToolsFileSystemHelper::RegisterSavedFileSystems, | |
| 243 this, | |
| 244 permitted_pathes)); | |
| 245 } | |
| 246 | |
| 247 void DevToolsFileSystemHelper::RegisterSavedFileSystems( | |
| 248 const std::vector<FilePath>& file_pathes) { | |
| 249 std::vector<FileSystem> file_systems; | |
| 250 std::vector<FilePath>::const_iterator it; | |
| 251 for (it = file_pathes.begin(); it != file_pathes.end(); ++it) { | |
| 252 std::string registered_name; | |
| 253 std::string file_system_id = RegisterFileSystem(web_contents_, | |
| 254 *it, | |
| 255 ®istered_name); | |
| 256 std::string file_system_path = it->AsUTF8Unsafe(); | |
| 257 FileSystem file_system(file_system_id, registered_name, file_system_path); | |
| 258 file_systems.push_back(file_system); | |
| 259 } | |
| 260 delegate_->FileSystemPermissionsLoaded(file_systems); | |
| 261 } | |
| 262 | |
| 263 void DevToolsFileSystemHelper::RevokePermission( | |
| 264 const std::string& file_system_path) { | |
| 265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 266 FilePath path = FilePath::FromUTF8Unsafe(file_system_path); | |
| 267 isolated_context()->RevokeFileSystemByPath(path); | |
| 268 | |
| 269 DictionaryPrefUpdate update(profile_->GetPrefs(), | |
| 270 prefs::kDevToolsSavedFileSystemPathes); | |
| 271 DictionaryValue* file_systems_pathes_value = update.Get(); | |
| 272 file_systems_pathes_value->RemoveWithoutPathExpansion(file_system_path, NULL); | |
| 273 } | |
| OLD | NEW |