Upstream version 10.39.225.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 "storage/browser/fileapi/file_system_backend.h"
26 #include "storage/browser/fileapi/file_system_context.h"
27 #include "storage/browser/fileapi/file_system_operation_runner.h"
28 #include "storage/browser/fileapi/file_system_url.h"
29 #include "ui/base/l10n/l10n_util.h"
30
31 using content::BrowserThread;
32 using storage::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   storage::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     int message;
146     if (file_path.Extension() == FILE_PATH_LITERAL(".dmg"))
147       message = IDS_FILE_BROWSER_ERROR_VIEWING_FILE_FOR_DMG;
148     else if (file_path.Extension() == FILE_PATH_LITERAL(".exe") ||
149              file_path.Extension() == FILE_PATH_LITERAL(".msi"))
150       message = IDS_FILE_BROWSER_ERROR_VIEWING_FILE_FOR_EXECUTABLE;
151     else
152       message = IDS_FILE_BROWSER_ERROR_VIEWING_FILE;
153     ShowWarningMessageBox(profile, file_path, message);
154   }
155 }
156
157 // Used to implement OpenItem().
158 void ContinueOpenItem(Profile* profile,
159                       const base::FilePath& file_path,
160                       const GURL& url,
161                       base::File::Error error) {
162   DCHECK_CURRENTLY_ON(BrowserThread::UI);
163
164   if (error == base::File::FILE_OK) {
165     // A directory exists at |url|. Open it with the file manager.
166     OpenFileManagerWithInternalActionId(profile, url, "open");
167   } else {
168     // |url| should be a file. Open it.
169     OpenFile(profile,
170              file_path,
171              url,
172              base::Bind(&OnContinueOpenItemCompleted, profile, file_path));
173   }
174 }
175
176 // Converts the |given_path| passed from external callers to the form that the
177 // file manager can correctly handle. It first migrates old Drive/Download
178 // folder path to the new formats, and then converts path to filesystem URL.
179 //
180 // When conversion fails, it shows a warning dialog UI and returns false.
181 bool ConvertPath(Profile* profile,
182                  const base::FilePath& given_path,
183                  base::FilePath* path,
184                  GURL* url) {
185   // The path may have been stored in preferences in old versions.
186   // We need migration here.
187   // TODO(kinaba): crbug.com/313539 remove it in the future.
188   if (!util::MigratePathFromOldFormat(profile, given_path, path))
189     *path = given_path;
190
191   if (!ConvertAbsoluteFilePathToFileSystemUrl(
192           profile, *path, kFileManagerAppId, url)) {
193     ShowWarningMessageBox(profile, *path,
194                           IDS_FILE_BROWSER_ERROR_UNRESOLVABLE_FILE);
195     return false;
196   }
197   return true;
198 }
199
200 }  // namespace
201
202 void OpenRemovableDrive(Profile* profile, const base::FilePath& file_path) {
203   DCHECK_CURRENTLY_ON(BrowserThread::UI);
204
205   base::FilePath converted_path;
206   GURL url;
207   if (!ConvertPath(profile, file_path, &converted_path, &url))
208     return;
209
210   OpenFileManagerWithInternalActionId(profile, url, "auto-open");
211 }
212
213 void OpenItem(Profile* profile, const base::FilePath& file_path) {
214   DCHECK_CURRENTLY_ON(BrowserThread::UI);
215
216   base::FilePath converted_path;
217   GURL url;
218   if (!ConvertPath(profile, file_path, &converted_path, &url))
219     return;
220
221   CheckIfDirectoryExists(
222       GetFileSystemContextForExtensionId(profile, kFileManagerAppId),
223       url,
224       base::Bind(&ContinueOpenItem, profile, converted_path, url));
225 }
226
227 void ShowItemInFolder(Profile* profile, const base::FilePath& file_path) {
228   DCHECK_CURRENTLY_ON(BrowserThread::UI);
229
230   base::FilePath converted_path;
231   GURL url;
232   if (!ConvertPath(profile, file_path, &converted_path, &url))
233     return;
234
235   // This action changes the selection so we do not reuse existing tabs.
236   OpenFileManagerWithInternalActionId(profile, url, "select");
237 }
238
239 }  // namespace util
240 }  // namespace file_manager