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 |