Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / file_manager / open_util.cc
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/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/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"
38
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;
44
45 namespace file_manager {
46 namespace util {
47 namespace {
48
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);
60 }
61
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();
69   if (!backend)
70     return false;
71   backend->GrantFullAccessToExtension(kFileManagerAppId);
72   return true;
73 }
74
75 // Executes the |task| for the file specified by |url|.
76 void ExecuteFileTaskForUrl(Profile* profile,
77                            const file_tasks::TaskDescriptor& task,
78                            const GURL& url) {
79   fileapi::FileSystemContext* file_system_context =
80       GetFileSystemContextForExtensionId(profile, kFileManagerAppId);
81
82   file_tasks::ExecuteFileTask(
83       profile,
84       GetFileManagerMainPageUrl(), // Executing the task on behalf of Files.app.
85       task,
86       std::vector<FileSystemURL>(1, file_system_context->CrackURL(url)),
87       file_tasks::FileTaskFinishedCallback());
88 }
89
90 // Opens the file manager for the specified |file_path|. Used to implement
91 // internal handlers of special action IDs:
92 //
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");
104
105   content::RecordAction(base::UserMetricsAction("ShowFileBrowserFullTab"));
106
107   GURL url;
108   if (!ConvertAbsoluteFilePathToFileSystemUrl(
109           profile, file_path, kFileManagerAppId, &url))
110     return;
111
112   file_tasks::TaskDescriptor task(kFileManagerAppId,
113                                   file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER,
114                                   action_id);
115   ExecuteFileTaskForUrl(profile, task, url);
116 }
117
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
120 // task is found).
121 bool OpenFile(Profile* profile, const base::FilePath& file_path) {
122   GURL url;
123   if (!ConvertAbsoluteFilePathToFileSystemUrl(
124           profile, file_path, kFileManagerAppId, &url))
125     return false;
126
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));
132
133   std::vector<GURL> file_urls;
134   file_urls.push_back(url);
135
136   std::vector<file_tasks::FullTaskDescriptor> tasks;
137   file_tasks::FindAllTypesOfTasks(
138       profile,
139       drive::util::GetDriveAppRegistryByProfile(profile),
140       path_mime_set,
141       file_urls,
142       &tasks);
143   if (tasks.empty())
144     return false;
145
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];
150       break;
151     }
152   }
153
154   ExecuteFileTaskForUrl(profile, chosen_task->task_descriptor(), url);
155   return true;
156 }
157
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));
163
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");
167   } else {
168     // |file_path| should be a file. Open it.
169     if (!OpenFile(profile, file_path))
170       ShowWarningMessageBox(profile, file_path);
171   }
172 }
173
174 // Used to implement CheckIfDirectoryExists().
175 void CheckIfDirectoryExistsOnIOThread(
176     scoped_refptr<fileapi::FileSystemContext> file_system_context,
177     const GURL& url,
178     const fileapi::FileSystemOperationRunner::StatusCallback& callback) {
179   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
180
181   fileapi::FileSystemURL file_system_url = file_system_context->CrackURL(url);
182   file_system_context->operation_runner()->DirectoryExists(
183       file_system_url, callback);
184 }
185
186 // Checks if a directory exists at |url|.
187 void CheckIfDirectoryExists(
188     scoped_refptr<fileapi::FileSystemContext> file_system_context,
189     const GURL& url,
190     const fileapi::FileSystemOperationRunner::StatusCallback& callback) {
191   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
192
193   BrowserThread::PostTask(
194       BrowserThread::IO, FROM_HERE,
195       base::Bind(&CheckIfDirectoryExistsOnIOThread,
196                  file_system_context,
197                  url,
198                  google_apis::CreateRelayCallback(callback)));
199 }
200
201 }  // namespace
202
203 void OpenRemovableDrive(Profile* profile, const base::FilePath& file_path) {
204   OpenFileManagerWithInternalActionId(profile, file_path, "auto-open");
205 }
206
207 void OpenItem(Profile* profile, const base::FilePath& file_path) {
208   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
209
210   GURL url;
211   if (!ConvertAbsoluteFilePathToFileSystemUrl(
212           profile, file_path, kFileManagerAppId, &url) ||
213       !GrantFileSystemAccessToFileBrowser(profile)) {
214     ShowWarningMessageBox(profile, file_path);
215     return;
216   }
217
218   scoped_refptr<fileapi::FileSystemContext> file_system_context =
219       GetFileSystemContextForExtensionId(
220           profile, kFileManagerAppId);
221
222   CheckIfDirectoryExists(file_system_context, url,
223                          base::Bind(&ContinueOpenItem, profile, file_path));
224 }
225
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");
229 }
230
231 }  // namespace util
232 }  // namespace file_manager