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

Side by Side Diff: chrome/browser/chromeos/extensions/file_manager/open_util.cc

Issue 23945002: file_manager: Move non-binding code to c/b/chromeos/file_manager (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 3 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 | Annotate | Revision Log
OLDNEW
(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/chromeos/extensions/file_manager/open_util.h"
6
7 #include "base/bind.h"
8 #include "base/files/file_path.h"
9 #include "base/logging.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/chromeos/extensions/file_manager/app_id.h"
12 #include "chrome/browser/chromeos/extensions/file_manager/file_browser_handlers. h"
13 #include "chrome/browser/chromeos/extensions/file_manager/file_tasks.h"
14 #include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h"
15 #include "chrome/browser/chromeos/extensions/file_manager/mime_util.h"
16 #include "chrome/browser/chromeos/extensions/file_manager/url_util.h"
17 #include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
18 #include "chrome/browser/extensions/extension_service.h"
19 #include "chrome/browser/extensions/extension_system.h"
20 #include "chrome/browser/google_apis/task_util.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/profiles/profile_manager.h"
23 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/browser_finder.h"
25 #include "chrome/browser/ui/browser_tabstrip.h"
26 #include "chrome/browser/ui/browser_window.h"
27 #include "chrome/browser/ui/extensions/application_launch.h"
28 #include "chrome/browser/ui/simple_message_box.h"
29 #include "chrome/common/extensions/api/file_browser_handlers/file_browser_handle r.h"
30 #include "content/public/browser/browser_thread.h"
31 #include "content/public/browser/storage_partition.h"
32 #include "content/public/browser/user_metrics.h"
33 #include "grit/generated_resources.h"
34 #include "ui/base/l10n/l10n_util.h"
35 #include "webkit/browser/fileapi/file_system_backend.h"
36 #include "webkit/browser/fileapi/file_system_context.h"
37 #include "webkit/browser/fileapi/file_system_operation_runner.h"
38 #include "webkit/browser/fileapi/file_system_url.h"
39
40 using content::BrowserContext;
41 using content::BrowserThread;
42 using content::UserMetricsAction;
43 using extensions::Extension;
44 using extensions::app_file_handler_util::FindFileHandlersForFiles;
45 using extensions::app_file_handler_util::PathAndMimeTypeSet;
46 using fileapi::FileSystemURL;
47
48 namespace file_manager {
49 namespace util {
50 namespace {
51
52 // Shows a warning message box saying that the file could not be opened.
53 void ShowWarningMessageBox(Profile* profile, const base::FilePath& file_path) {
54 // TODO: if FindOrCreateTabbedBrowser creates a new browser the returned
55 // browser is leaked.
56 Browser* browser =
57 chrome::FindOrCreateTabbedBrowser(profile,
58 chrome::HOST_DESKTOP_TYPE_ASH);
59 chrome::ShowMessageBox(
60 browser->window()->GetNativeWindow(),
61 l10n_util::GetStringFUTF16(
62 IDS_FILE_BROWSER_ERROR_VIEWING_FILE_TITLE,
63 UTF8ToUTF16(file_path.BaseName().value())),
64 l10n_util::GetStringUTF16(IDS_FILE_BROWSER_ERROR_VIEWING_FILE),
65 chrome::MESSAGE_BOX_TYPE_WARNING);
66 }
67
68 // Grants file system access to the file manager.
69 bool GrantFileSystemAccessToFileBrowser(Profile* profile) {
70 // The file manager always runs in the site for its extension id, so that
71 // is the site for which file access permissions should be granted.
72 fileapi::ExternalFileSystemBackend* backend =
73 GetFileSystemContextForExtensionId(
74 profile, kFileManagerAppId)->external_backend();
75 if (!backend)
76 return false;
77 backend->GrantFullAccessToExtension(kFileManagerAppId);
78 return true;
79 }
80
81 // Executes the |task| for the file specified by |url|.
82 void ExecuteFileTaskForUrl(Profile* profile,
83 const file_tasks::TaskDescriptor& task,
84 const GURL& url) {
85 // If the file manager has not been open yet then it did not request access
86 // to the file system. Do it now.
87 if (!GrantFileSystemAccessToFileBrowser(profile))
88 return;
89
90 fileapi::FileSystemContext* file_system_context =
91 GetFileSystemContextForExtensionId(
92 profile, kFileManagerAppId);
93
94 // We are executing the task on behalf of the file manager.
95 const GURL source_url = GetFileManagerMainPageUrl();
96 std::vector<FileSystemURL> urls;
97 urls.push_back(file_system_context->CrackURL(url));
98
99 file_tasks::ExecuteFileTask(
100 profile,
101 source_url,
102 kFileManagerAppId,
103 0, // no tab id
104 task,
105 urls,
106 file_tasks::FileTaskFinishedCallback());
107 }
108
109 // Opens the file manager for the specified |file_path|. Used to implement
110 // internal handlers of special action IDs:
111 //
112 // "open" - Open the file manager for the given folder.
113 // "auto-open" - Open the file manager for the given removal drive and close
114 // the file manager when the removal drive is unmounted.
115 // "select" - Open the file manager for the given file. The folder containing
116 // the file will be opened with the file selected.
117 void OpenFileManagerWithInternalActionId(const base::FilePath& file_path,
118 const std::string& action_id) {
119 DCHECK(action_id == "auto-open" ||
120 action_id == "open" ||
121 action_id == "select");
122
123 content::RecordAction(UserMetricsAction("ShowFileBrowserFullTab"));
124 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
125
126 GURL url;
127 if (!ConvertAbsoluteFilePathToFileSystemUrl(
128 profile, file_path, kFileManagerAppId, &url))
129 return;
130
131 file_tasks::TaskDescriptor task(kFileManagerAppId,
132 file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER,
133 action_id);
134 ExecuteFileTaskForUrl(profile, task, url);
135 }
136
137 // Opens the file specified by |file_path| and |url| with a file handler,
138 // preferably the default handler for the type of the file. Returns false if
139 // no file handler is found.
140 bool OpenFileWithFileHandler(Profile* profile,
141 const base::FilePath& file_path,
142 const GURL& url,
143 const std::string& mime_type,
144 const std::string& default_task_id) {
145 ExtensionService* service = profile->GetExtensionService();
146 if (!service)
147 return false;
148
149 PathAndMimeTypeSet files;
150 files.insert(std::make_pair(file_path, mime_type));
151 const extensions::FileHandlerInfo* first_handler = NULL;
152 const extensions::Extension* extension_for_first_handler = NULL;
153
154 // If we find the default handler, we execute it immediately, but otherwise,
155 // we remember the first handler, and if there was no default handler, simply
156 // execute the first one.
157 for (ExtensionSet::const_iterator iter = service->extensions()->begin();
158 iter != service->extensions()->end();
159 ++iter) {
160 const Extension* extension = iter->get();
161
162 // We don't support using hosted apps to open files.
163 if (!extension->is_platform_app())
164 continue;
165
166 // We only support apps that specify "incognito: split" if in incognito
167 // mode.
168 if (profile->IsOffTheRecord() &&
169 !service->IsIncognitoEnabled(extension->id()))
170 continue;
171
172 typedef std::vector<const extensions::FileHandlerInfo*> FileHandlerList;
173 FileHandlerList file_handlers = FindFileHandlersForFiles(*extension, files);
174 for (FileHandlerList::iterator i = file_handlers.begin();
175 i != file_handlers.end(); ++i) {
176 const extensions::FileHandlerInfo* handler = *i;
177 std::string task_id = file_tasks::MakeTaskID(
178 extension->id(),
179 file_tasks::TASK_TYPE_FILE_HANDLER,
180 handler->id);
181 if (task_id == default_task_id) {
182 file_tasks::TaskDescriptor task(extension->id(),
183 file_tasks::TASK_TYPE_FILE_HANDLER,
184 handler->id);
185 ExecuteFileTaskForUrl(profile, task, url);
186 return true;
187
188 } else if (!first_handler) {
189 first_handler = handler;
190 extension_for_first_handler = extension;
191 }
192 }
193 }
194 if (first_handler) {
195 file_tasks::TaskDescriptor task(extension_for_first_handler->id(),
196 file_tasks::TASK_TYPE_FILE_HANDLER,
197 first_handler->id);
198 ExecuteFileTaskForUrl(profile, task, url);
199 return true;
200 }
201 return false;
202 }
203
204 // Opens the file specified by |file_path| and |url| with the file browser
205 // handler specified by |handler|. Returns false if failed to open the file.
206 bool OpenFileWithFileBrowserHandler(Profile* profile,
207 const base::FilePath& file_path,
208 const FileBrowserHandler& handler,
209 const GURL& url) {
210 file_tasks::TaskDescriptor task(handler.extension_id(),
211 file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER,
212 handler.id());
213 ExecuteFileTaskForUrl(profile, task, url);
214 return true;
215 }
216
217 // Opens the file specified by |file_path| with a handler (either of file
218 // browser handler or file handler, preferably the default handler for the
219 // type of the file), or opens the file with the browser. Returns false if
220 // failed to open the file.
221 bool OpenFileWithHandler(Profile* profile, const base::FilePath& file_path) {
222 GURL url;
223 if (!ConvertAbsoluteFilePathToFileSystemUrl(
224 profile, file_path, kFileManagerAppId, &url))
225 return false;
226
227 std::string mime_type = GetMimeTypeForPath(file_path);
228 std::string default_task_id = file_tasks::GetDefaultTaskIdFromPrefs(
229 *profile->GetPrefs(), mime_type, file_path.Extension());
230
231 // We choose the file handler from the following in decreasing priority or
232 // fail if none support the file type:
233 // 1. default file browser handler
234 // 2. default file handler
235 // 3. a fallback handler (e.g. opening in the browser)
236 // 4. non-default file handler
237 // 5. non-default file browser handler
238 // Note that there can be at most one of default extension and default app.
239 const FileBrowserHandler* handler =
240 file_browser_handlers::FindFileBrowserHandlerForURLAndPath(
241 profile, url, file_path);
242 if (!handler) {
243 return OpenFileWithFileHandler(
244 profile, file_path, url, mime_type, default_task_id);
245 }
246
247 const file_tasks::TaskDescriptor task_descriptor(
248 handler->extension_id(),
249 file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER,
250 handler->id());
251 const std::string handler_task_id =
252 file_tasks::TaskDescriptorToId(task_descriptor);
253 if (handler_task_id != default_task_id &&
254 !file_browser_handlers::IsFallbackFileBrowserHandler(task_descriptor) &&
255 OpenFileWithFileHandler(
256 profile, file_path, url, mime_type, default_task_id)) {
257 return true;
258 }
259 return OpenFileWithFileBrowserHandler(profile, file_path, *handler, url);
260 }
261
262 // Used to implement OpenItem().
263 void ContinueOpenItem(Profile* profile,
264 const base::FilePath& file_path,
265 base::PlatformFileError error) {
266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
267
268 if (error == base::PLATFORM_FILE_OK) {
269 // A directory exists at |file_path|. Open it with the file manager.
270 OpenFileManagerWithInternalActionId(file_path, "open");
271 } else {
272 // |file_path| should be a file. Open it with a handler.
273 if (!OpenFileWithHandler(profile, file_path))
274 ShowWarningMessageBox(profile, file_path);
275 }
276 }
277
278 // Used to implement CheckIfDirectoryExists().
279 void CheckIfDirectoryExistsOnIOThread(
280 scoped_refptr<fileapi::FileSystemContext> file_system_context,
281 const GURL& url,
282 const fileapi::FileSystemOperationRunner::StatusCallback& callback) {
283 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
284
285 fileapi::FileSystemURL file_system_url = file_system_context->CrackURL(url);
286 file_system_context->operation_runner()->DirectoryExists(
287 file_system_url, callback);
288 }
289
290 // Checks if a directory exists at |url|.
291 void CheckIfDirectoryExists(
292 scoped_refptr<fileapi::FileSystemContext> file_system_context,
293 const GURL& url,
294 const fileapi::FileSystemOperationRunner::StatusCallback& callback) {
295 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
296
297 BrowserThread::PostTask(
298 BrowserThread::IO, FROM_HERE,
299 base::Bind(&CheckIfDirectoryExistsOnIOThread,
300 file_system_context,
301 url,
302 google_apis::CreateRelayCallback(callback)));
303 }
304
305 } // namespace
306
307 void OpenRemovableDrive(const base::FilePath& file_path) {
308 OpenFileManagerWithInternalActionId(file_path, "auto-open");
309 }
310
311 void OpenItem(const base::FilePath& file_path) {
312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
313
314 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
315 GURL url;
316 if (!ConvertAbsoluteFilePathToFileSystemUrl(
317 profile, file_path, kFileManagerAppId, &url) ||
318 !GrantFileSystemAccessToFileBrowser(profile)) {
319 ShowWarningMessageBox(profile, file_path);
320 return;
321 }
322
323 scoped_refptr<fileapi::FileSystemContext> file_system_context =
324 GetFileSystemContextForExtensionId(
325 profile, kFileManagerAppId);
326
327 CheckIfDirectoryExists(file_system_context, url,
328 base::Bind(&ContinueOpenItem, profile, file_path));
329 }
330
331 void ShowItemInFolder(const base::FilePath& file_path) {
332 // This action changes the selection so we do not reuse existing tabs.
333 OpenFileManagerWithInternalActionId(file_path, "select");
334 }
335
336 } // namespace util
337 } // namespace file_manager
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698