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.
5 #include "chrome/browser/chromeos/file_manager/open_util.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/drive/file_system_util.h"
12 #include "chrome/browser/chromeos/file_manager/app_id.h"
13 #include "chrome/browser/chromeos/file_manager/file_browser_handlers.h"
14 #include "chrome/browser/chromeos/file_manager/file_tasks.h"
15 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
16 #include "chrome/browser/chromeos/file_manager/mime_util.h"
17 #include "chrome/browser/chromeos/file_manager/url_util.h"
18 #include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
19 #include "chrome/browser/extensions/extension_service.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/browser/ui/browser_finder.h"
23 #include "chrome/browser/ui/browser_tabstrip.h"
24 #include "chrome/browser/ui/browser_window.h"
25 #include "chrome/browser/ui/extensions/application_launch.h"
26 #include "chrome/browser/ui/simple_message_box.h"
27 #include "content/public/browser/browser_thread.h"
28 #include "content/public/browser/storage_partition.h"
29 #include "content/public/browser/user_metrics.h"
30 #include "extensions/browser/extension_system.h"
31 #include "google_apis/drive/task_util.h"
32 #include "grit/generated_resources.h"
33 #include "ui/base/l10n/l10n_util.h"
34 #include "webkit/browser/fileapi/file_system_backend.h"
35 #include "webkit/browser/fileapi/file_system_context.h"
36 #include "webkit/browser/fileapi/file_system_operation_runner.h"
37 #include "webkit/browser/fileapi/file_system_url.h"
39 using content::BrowserThread;
40 using extensions::Extension;
41 using extensions::app_file_handler_util::FindFileHandlersForFiles;
42 using extensions::app_file_handler_util::PathAndMimeTypeSet;
43 using fileapi::FileSystemURL;
45 namespace file_manager {
49 // Shows a warning message box saying that the file could not be opened.
50 void ShowWarningMessageBox(Profile* profile, const base::FilePath& file_path) {
51 Browser* browser = chrome::FindTabbedBrowser(
52 profile, false, chrome::HOST_DESKTOP_TYPE_ASH);
53 chrome::ShowMessageBox(
54 browser ? browser->window()->GetNativeWindow() : NULL,
55 l10n_util::GetStringFUTF16(
56 IDS_FILE_BROWSER_ERROR_VIEWING_FILE_TITLE,
57 base::UTF8ToUTF16(file_path.BaseName().AsUTF8Unsafe())),
58 l10n_util::GetStringUTF16(IDS_FILE_BROWSER_ERROR_VIEWING_FILE),
59 chrome::MESSAGE_BOX_TYPE_WARNING);
62 // Grants file system access to the file manager.
63 bool GrantFileSystemAccessToFileBrowser(Profile* profile) {
64 // The file manager always runs in the site for its extension id, so that
65 // is the site for which file access permissions should be granted.
66 fileapi::ExternalFileSystemBackend* backend =
67 GetFileSystemContextForExtensionId(
68 profile, kFileManagerAppId)->external_backend();
71 backend->GrantFullAccessToExtension(kFileManagerAppId);
75 // Executes the |task| for the file specified by |url|.
76 void ExecuteFileTaskForUrl(Profile* profile,
77 const file_tasks::TaskDescriptor& task,
79 fileapi::FileSystemContext* file_system_context =
80 GetFileSystemContextForExtensionId(profile, kFileManagerAppId);
82 file_tasks::ExecuteFileTask(
84 GetFileManagerMainPageUrl(), // Executing the task on behalf of Files.app.
86 std::vector<FileSystemURL>(1, file_system_context->CrackURL(url)),
87 file_tasks::FileTaskFinishedCallback());
90 // Opens the file manager for the specified |file_path|. Used to implement
91 // internal handlers of special action IDs:
93 // "open" - Open the file manager for the given folder.
94 // "auto-open" - Open the file manager for the given removal drive and close
95 // the file manager when the removal drive is unmounted.
96 // "select" - Open the file manager for the given file. The folder containing
97 // the file will be opened with the file selected.
98 void OpenFileManagerWithInternalActionId(Profile* profile,
99 const base::FilePath& file_path,
100 const std::string& action_id) {
101 DCHECK(action_id == "auto-open" ||
102 action_id == "open" ||
103 action_id == "select");
105 content::RecordAction(base::UserMetricsAction("ShowFileBrowserFullTab"));
108 if (!ConvertAbsoluteFilePathToFileSystemUrl(
109 profile, file_path, kFileManagerAppId, &url))
112 file_tasks::TaskDescriptor task(kFileManagerAppId,
113 file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER,
115 ExecuteFileTaskForUrl(profile, task, url);
118 // Opens the file specified by |file_path| by finding and executing a file
119 // task for the file. Returns false if failed to open the file (i.e. no file
121 bool OpenFile(Profile* profile, const base::FilePath& file_path) {
123 if (!ConvertAbsoluteFilePathToFileSystemUrl(
124 profile, file_path, kFileManagerAppId, &url))
127 // The file is opened per the file extension, hence extension-less files
128 // cannot be opened properly.
129 std::string mime_type = GetMimeTypeForPath(file_path);
130 extensions::app_file_handler_util::PathAndMimeTypeSet path_mime_set;
131 path_mime_set.insert(std::make_pair(file_path, mime_type));
133 std::vector<GURL> file_urls;
134 file_urls.push_back(url);
136 std::vector<file_tasks::FullTaskDescriptor> tasks;
137 file_tasks::FindAllTypesOfTasks(
139 drive::util::GetDriveAppRegistryByProfile(profile),
146 const file_tasks::FullTaskDescriptor* chosen_task = &tasks[0];
147 for (size_t i = 0; i < tasks.size(); ++i) {
148 if (tasks[i].is_default()) {
149 chosen_task = &tasks[i];
154 ExecuteFileTaskForUrl(profile, chosen_task->task_descriptor(), url);
158 // Used to implement OpenItem().
159 void ContinueOpenItem(Profile* profile,
160 const base::FilePath& file_path,
161 base::File::Error error) {
162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
164 if (error == base::File::FILE_OK) {
165 // A directory exists at |file_path|. Open it with the file manager.
166 OpenFileManagerWithInternalActionId(profile, file_path, "open");
168 // |file_path| should be a file. Open it.
169 if (!OpenFile(profile, file_path))
170 ShowWarningMessageBox(profile, file_path);
174 // Used to implement CheckIfDirectoryExists().
175 void CheckIfDirectoryExistsOnIOThread(
176 scoped_refptr<fileapi::FileSystemContext> file_system_context,
178 const fileapi::FileSystemOperationRunner::StatusCallback& callback) {
179 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
181 fileapi::FileSystemURL file_system_url = file_system_context->CrackURL(url);
182 file_system_context->operation_runner()->DirectoryExists(
183 file_system_url, callback);
186 // Checks if a directory exists at |url|.
187 void CheckIfDirectoryExists(
188 scoped_refptr<fileapi::FileSystemContext> file_system_context,
190 const fileapi::FileSystemOperationRunner::StatusCallback& callback) {
191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
193 BrowserThread::PostTask(
194 BrowserThread::IO, FROM_HERE,
195 base::Bind(&CheckIfDirectoryExistsOnIOThread,
198 google_apis::CreateRelayCallback(callback)));
203 void OpenRemovableDrive(Profile* profile, const base::FilePath& file_path) {
204 OpenFileManagerWithInternalActionId(profile, file_path, "auto-open");
207 void OpenItem(Profile* profile, const base::FilePath& file_path) {
208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
211 if (!ConvertAbsoluteFilePathToFileSystemUrl(
212 profile, file_path, kFileManagerAppId, &url) ||
213 !GrantFileSystemAccessToFileBrowser(profile)) {
214 ShowWarningMessageBox(profile, file_path);
218 scoped_refptr<fileapi::FileSystemContext> file_system_context =
219 GetFileSystemContextForExtensionId(
220 profile, kFileManagerAppId);
222 CheckIfDirectoryExists(file_system_context, url,
223 base::Bind(&ContinueOpenItem, profile, file_path));
226 void ShowItemInFolder(Profile* profile, const base::FilePath& file_path) {
227 // This action changes the selection so we do not reuse existing tabs.
228 OpenFileManagerWithInternalActionId(profile, file_path, "select");
232 } // namespace file_manager