Upstream version 9.38.198.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_tasks.h"
14 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
15 #include "chrome/browser/chromeos/file_manager/path_util.h"
16 #include "chrome/browser/chromeos/file_manager/url_util.h"
17 #include "chrome/browser/extensions/api/file_handlers/mime_util.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_finder.h"
20 #include "chrome/browser/ui/browser_window.h"
21 #include "chrome/browser/ui/simple_message_box.h"
22 #include "chrome/grit/generated_resources.h"
23 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/user_metrics.h"
25 #include "ui/base/l10n/l10n_util.h"
26 #include "webkit/browser/fileapi/file_system_backend.h"
27 #include "webkit/browser/fileapi/file_system_context.h"
28 #include "webkit/browser/fileapi/file_system_operation_runner.h"
29 #include "webkit/browser/fileapi/file_system_url.h"
30
31 using content::BrowserThread;
32 using fileapi::FileSystemURL;
33
34 namespace file_manager {
35 namespace util {
36 namespace {
37
38 // Shows a warning message box saying that the file could not be opened.
39 void ShowWarningMessageBox(Profile* profile,
40                            const base::FilePath& file_path,
41                            int message_id) {
42   Browser* browser = chrome::FindTabbedBrowser(
43       profile, false, chrome::HOST_DESKTOP_TYPE_ASH);
44   chrome::ShowMessageBox(
45       browser ? browser->window()->GetNativeWindow() : NULL,
46       l10n_util::GetStringFUTF16(
47           IDS_FILE_BROWSER_ERROR_VIEWING_FILE_TITLE,
48           base::UTF8ToUTF16(file_path.BaseName().AsUTF8Unsafe())),
49       l10n_util::GetStringUTF16(message_id),
50       chrome::MESSAGE_BOX_TYPE_WARNING);
51 }
52
53 // Executes the |task| for the file specified by |url|.
54 void ExecuteFileTaskForUrl(Profile* profile,
55                            const file_tasks::TaskDescriptor& task,
56                            const GURL& url) {
57   fileapi::FileSystemContext* file_system_context =
58       GetFileSystemContextForExtensionId(profile, kFileManagerAppId);
59
60   file_tasks::ExecuteFileTask(
61       profile,
62       GetFileManagerMainPageUrl(), // Executing the task on behalf of Files.app.
63       task,
64       std::vector<FileSystemURL>(1, file_system_context->CrackURL(url)),
65       file_tasks::FileTaskFinishedCallback());
66 }
67
68 // Opens the file manager for the specified |url|. Used to implement
69 // internal handlers of special action IDs:
70 //
71 // "open" - Open the file manager for the given folder.
72 // "auto-open" - Open the file manager for the given removal drive and close
73 //               the file manager when the removal drive is unmounted.
74 // "select" - Open the file manager for the given file. The folder containing
75 //            the file will be opened with the file selected.
76 void OpenFileManagerWithInternalActionId(Profile* profile,
77                                          const GURL& url,
78                                          const std::string& action_id) {
79   DCHECK(action_id == "auto-open" ||
80          action_id == "open" ||
81          action_id == "select");
82   content::RecordAction(base::UserMetricsAction("ShowFileBrowserFullTab"));
83
84   file_tasks::TaskDescriptor task(kFileManagerAppId,
85                                   file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER,
86                                   action_id);
87   ExecuteFileTaskForUrl(profile, task, url);
88 }
89
90 // Opens the file with fetched MIME type and calls the callback.
91 void OpenFileWithMimeType(Profile* profile,
92                           const base::FilePath& path,
93                           const GURL& url,
94                           const base::Callback<void(bool)>& callback,
95                           const std::string& mime_type) {
96   extensions::app_file_handler_util::PathAndMimeTypeSet path_mime_set;
97   path_mime_set.insert(std::make_pair(path, mime_type));
98
99   std::vector<GURL> file_urls;
100   file_urls.push_back(url);
101
102   std::vector<file_tasks::FullTaskDescriptor> tasks;
103   file_tasks::FindAllTypesOfTasks(
104       profile,
105       drive::util::GetDriveAppRegistryByProfile(profile),
106       path_mime_set,
107       file_urls,
108       &tasks);
109
110   if (tasks.empty()) {
111     callback.Run(false);
112     return;
113   }
114
115   const file_tasks::FullTaskDescriptor* chosen_task = &tasks[0];
116   for (size_t i = 0; i < tasks.size(); ++i) {
117     if (tasks[i].is_default()) {
118       chosen_task = &tasks[i];
119       break;
120     }
121   }
122
123   ExecuteFileTaskForUrl(profile, chosen_task->task_descriptor(), url);
124   callback.Run(true);
125 }
126
127 // Opens the file specified by |url| by finding and executing a file task for
128 // the file. In case of success, calls |callback| with true. Otherwise the
129 // returned value is false.
130 void OpenFile(Profile* profile,
131               const base::FilePath& path,
132               const GURL& url,
133               const base::Callback<void(bool)>& callback) {
134   extensions::app_file_handler_util::GetMimeTypeForLocalPath(
135       profile,
136       path,
137       base::Bind(&OpenFileWithMimeType, profile, path, url, callback));
138 }
139
140 // Called when execution of ContinueOpenItem() is completed.
141 void OnContinueOpenItemCompleted(Profile* profile,
142                                  const base::FilePath& file_path,
143                                  bool result) {
144   if (!result) {
145     ShowWarningMessageBox(
146         profile, file_path, IDS_FILE_BROWSER_ERROR_VIEWING_FILE);
147   }
148 }
149
150 // Used to implement OpenItem().
151 void ContinueOpenItem(Profile* profile,
152                       const base::FilePath& file_path,
153                       const GURL& url,
154                       base::File::Error error) {
155   DCHECK_CURRENTLY_ON(BrowserThread::UI);
156
157   if (error == base::File::FILE_OK) {
158     // A directory exists at |url|. Open it with the file manager.
159     OpenFileManagerWithInternalActionId(profile, url, "open");
160   } else {
161     // |url| should be a file. Open it.
162     OpenFile(profile,
163              file_path,
164              url,
165              base::Bind(&OnContinueOpenItemCompleted, profile, file_path));
166   }
167 }
168
169 // Converts the |given_path| passed from external callers to the form that the
170 // file manager can correctly handle. It first migrates old Drive/Download
171 // folder path to the new formats, and then converts path to filesystem URL.
172 //
173 // When conversion fails, it shows a warning dialog UI and returns false.
174 bool ConvertPath(Profile* profile,
175                  const base::FilePath& given_path,
176                  base::FilePath* path,
177                  GURL* url) {
178   // The path may have been stored in preferences in old versions.
179   // We need migration here.
180   // TODO(kinaba): crbug.com/313539 remove it in the future.
181   if (!util::MigratePathFromOldFormat(profile, given_path, path))
182     *path = given_path;
183
184   if (!ConvertAbsoluteFilePathToFileSystemUrl(
185           profile, *path, kFileManagerAppId, url)) {
186     ShowWarningMessageBox(profile, *path,
187                           IDS_FILE_BROWSER_ERROR_UNRESOLVABLE_FILE);
188     return false;
189   }
190   return true;
191 }
192
193 }  // namespace
194
195 void OpenRemovableDrive(Profile* profile, const base::FilePath& file_path) {
196   DCHECK_CURRENTLY_ON(BrowserThread::UI);
197
198   base::FilePath converted_path;
199   GURL url;
200   if (!ConvertPath(profile, file_path, &converted_path, &url))
201     return;
202
203   OpenFileManagerWithInternalActionId(profile, url, "auto-open");
204 }
205
206 void OpenItem(Profile* profile, const base::FilePath& file_path) {
207   DCHECK_CURRENTLY_ON(BrowserThread::UI);
208
209   base::FilePath converted_path;
210   GURL url;
211   if (!ConvertPath(profile, file_path, &converted_path, &url))
212     return;
213
214   CheckIfDirectoryExists(
215       GetFileSystemContextForExtensionId(profile, kFileManagerAppId),
216       url,
217       base::Bind(&ContinueOpenItem, profile, converted_path, url));
218 }
219
220 void ShowItemInFolder(Profile* profile, const base::FilePath& file_path) {
221   DCHECK_CURRENTLY_ON(BrowserThread::UI);
222
223   base::FilePath converted_path;
224   GURL url;
225   if (!ConvertPath(profile, file_path, &converted_path, &url))
226     return;
227
228   // This action changes the selection so we do not reuse existing tabs.
229   OpenFileManagerWithInternalActionId(profile, url, "select");
230 }
231
232 }  // namespace util
233 }  // namespace file_manager