OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/file_manager/open_util.h" | 5 #include "chrome/browser/chromeos/file_manager/open_util.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
11 #include "chrome/browser/chromeos/drive/file_system_util.h" | 11 #include "chrome/browser/chromeos/drive/file_system_util.h" |
12 #include "chrome/browser/chromeos/file_manager/app_id.h" | 12 #include "chrome/browser/chromeos/file_manager/app_id.h" |
13 #include "chrome/browser/chromeos/file_manager/file_tasks.h" | 13 #include "chrome/browser/chromeos/file_manager/file_tasks.h" |
14 #include "chrome/browser/chromeos/file_manager/fileapi_util.h" | 14 #include "chrome/browser/chromeos/file_manager/fileapi_util.h" |
15 #include "chrome/browser/chromeos/file_manager/path_util.h" | 15 #include "chrome/browser/chromeos/file_manager/path_util.h" |
16 #include "chrome/browser/chromeos/file_manager/url_util.h" | 16 #include "chrome/browser/chromeos/file_manager/url_util.h" |
17 #include "chrome/browser/extensions/api/file_handlers/mime_util.h" | 17 #include "chrome/browser/extensions/api/file_handlers/mime_util.h" |
| 18 #include "chrome/browser/platform_util_internal.h" |
18 #include "chrome/browser/ui/browser.h" | 19 #include "chrome/browser/ui/browser.h" |
19 #include "chrome/browser/ui/browser_finder.h" | 20 #include "chrome/browser/ui/browser_finder.h" |
20 #include "chrome/browser/ui/browser_window.h" | 21 #include "chrome/browser/ui/browser_window.h" |
21 #include "chrome/browser/ui/simple_message_box.h" | 22 #include "chrome/browser/ui/simple_message_box.h" |
22 #include "chrome/grit/generated_resources.h" | 23 #include "chrome/grit/generated_resources.h" |
23 #include "content/public/browser/browser_thread.h" | 24 #include "content/public/browser/browser_thread.h" |
24 #include "content/public/browser/user_metrics.h" | 25 #include "content/public/browser/user_metrics.h" |
25 #include "storage/browser/fileapi/file_system_backend.h" | 26 #include "storage/browser/fileapi/file_system_backend.h" |
26 #include "storage/browser/fileapi/file_system_context.h" | 27 #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_operation_runner.h" |
28 #include "storage/browser/fileapi/file_system_url.h" | 29 #include "storage/browser/fileapi/file_system_url.h" |
29 #include "ui/base/l10n/l10n_util.h" | 30 #include "ui/base/l10n/l10n_util.h" |
30 | 31 |
31 using content::BrowserThread; | 32 using content::BrowserThread; |
32 using storage::FileSystemURL; | 33 using storage::FileSystemURL; |
33 | 34 |
34 namespace file_manager { | 35 namespace file_manager { |
35 namespace util { | 36 namespace util { |
36 namespace { | 37 namespace { |
37 | 38 |
38 // Shows a warning message box saying that the file could not be opened. | 39 bool shell_operations_allowed = true; |
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 | 40 |
53 // Executes the |task| for the file specified by |url|. | 41 // Executes the |task| for the file specified by |url|. |
54 void ExecuteFileTaskForUrl(Profile* profile, | 42 void ExecuteFileTaskForUrl(Profile* profile, |
55 const file_tasks::TaskDescriptor& task, | 43 const file_tasks::TaskDescriptor& task, |
56 const GURL& url) { | 44 const GURL& url) { |
| 45 if (!shell_operations_allowed) |
| 46 return; |
57 storage::FileSystemContext* file_system_context = | 47 storage::FileSystemContext* file_system_context = |
58 GetFileSystemContextForExtensionId(profile, kFileManagerAppId); | 48 GetFileSystemContextForExtensionId(profile, kFileManagerAppId); |
59 | 49 |
60 file_tasks::ExecuteFileTask( | 50 file_tasks::ExecuteFileTask( |
61 profile, | 51 profile, |
62 GetFileManagerMainPageUrl(), // Executing the task on behalf of Files.app. | 52 GetFileManagerMainPageUrl(), // Executing the task on behalf of Files.app. |
63 task, | 53 task, |
64 std::vector<FileSystemURL>(1, file_system_context->CrackURL(url)), | 54 std::vector<FileSystemURL>(1, file_system_context->CrackURL(url)), |
65 file_tasks::FileTaskFinishedCallback()); | 55 file_tasks::FileTaskFinishedCallback()); |
66 } | 56 } |
67 | 57 |
68 // Opens the file manager for the specified |url|. Used to implement | 58 // Opens the file manager for the specified |url|. Used to implement |
69 // internal handlers of special action IDs: | 59 // internal handlers of special action IDs: |
70 // | 60 // |
71 // "open" - Open the file manager for the given folder. | 61 // "open" - Open the file manager for the given folder. |
72 // "select" - Open the file manager for the given file. The folder containing | 62 // "select" - Open the file manager for the given file. The folder containing |
73 // the file will be opened with the file selected. | 63 // the file will be opened with the file selected. |
74 void OpenFileManagerWithInternalActionId(Profile* profile, | 64 void OpenFileManagerWithInternalActionId(Profile* profile, |
75 const GURL& url, | 65 const GURL& url, |
76 const std::string& action_id) { | 66 const std::string& action_id) { |
77 DCHECK(action_id == "open" || action_id == "select"); | 67 DCHECK(action_id == "open" || action_id == "select"); |
| 68 if (!shell_operations_allowed) |
| 69 return; |
78 content::RecordAction(base::UserMetricsAction("ShowFileBrowserFullTab")); | 70 content::RecordAction(base::UserMetricsAction("ShowFileBrowserFullTab")); |
79 | 71 |
80 file_tasks::TaskDescriptor task(kFileManagerAppId, | 72 file_tasks::TaskDescriptor task(kFileManagerAppId, |
81 file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER, | 73 file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER, |
82 action_id); | 74 action_id); |
83 ExecuteFileTaskForUrl(profile, task, url); | 75 ExecuteFileTaskForUrl(profile, task, url); |
84 } | 76 } |
85 | 77 |
86 // Opens the file with fetched MIME type and calls the callback. | 78 // Opens the file with fetched MIME type and warns the user on failure. |
87 void OpenFileWithMimeType(Profile* profile, | 79 void OpenFileWithMimeType(Profile* profile, |
| 80 const platform_util::OpenOperationCallback& callback, |
88 const base::FilePath& path, | 81 const base::FilePath& path, |
89 const GURL& url, | 82 const GURL& url, |
90 const base::Callback<void(bool)>& callback, | |
91 const std::string& mime_type) { | 83 const std::string& mime_type) { |
92 extensions::app_file_handler_util::PathAndMimeTypeSet path_mime_set; | 84 extensions::app_file_handler_util::PathAndMimeTypeSet path_mime_set; |
93 path_mime_set.insert(std::make_pair(path, mime_type)); | 85 path_mime_set.insert(std::make_pair(path, mime_type)); |
94 | 86 |
95 std::vector<GURL> file_urls; | 87 std::vector<GURL> file_urls; |
96 file_urls.push_back(url); | 88 file_urls.push_back(url); |
97 | 89 |
98 std::vector<file_tasks::FullTaskDescriptor> tasks; | 90 std::vector<file_tasks::FullTaskDescriptor> tasks; |
99 file_tasks::FindAllTypesOfTasks( | 91 file_tasks::FindAllTypesOfTasks( |
100 profile, | 92 profile, |
101 drive::util::GetDriveAppRegistryByProfile(profile), | 93 drive::util::GetDriveAppRegistryByProfile(profile), |
102 path_mime_set, | 94 path_mime_set, |
103 file_urls, | 95 file_urls, |
104 &tasks); | 96 &tasks); |
105 | 97 |
106 if (tasks.empty()) { | 98 if (tasks.empty()) { |
107 callback.Run(false); | 99 callback.Run(platform_util::OPEN_FAILED_NO_HANLDER_FOR_FILE_TYPE); |
108 return; | 100 return; |
109 } | 101 } |
110 | 102 |
111 const file_tasks::FullTaskDescriptor* chosen_task = &tasks[0]; | 103 const file_tasks::FullTaskDescriptor* chosen_task = &tasks[0]; |
112 for (size_t i = 0; i < tasks.size(); ++i) { | 104 for (const auto& task : tasks) { |
113 if (tasks[i].is_default()) { | 105 if (task.is_default()) { |
114 chosen_task = &tasks[i]; | 106 chosen_task = &task; |
115 break; | 107 break; |
116 } | 108 } |
117 } | 109 } |
118 | 110 |
119 ExecuteFileTaskForUrl(profile, chosen_task->task_descriptor(), url); | 111 if (shell_operations_allowed) |
120 callback.Run(true); | 112 ExecuteFileTaskForUrl(profile, chosen_task->task_descriptor(), url); |
| 113 callback.Run(platform_util::OPEN_SUCCEEDED); |
121 } | 114 } |
122 | 115 |
123 // Opens the file specified by |url| by finding and executing a file task for | |
124 // the file. In case of success, calls |callback| with true. Otherwise the | |
125 // returned value is false. | |
126 void OpenFile(Profile* profile, | |
127 const base::FilePath& path, | |
128 const GURL& url, | |
129 const base::Callback<void(bool)>& callback) { | |
130 extensions::app_file_handler_util::GetMimeTypeForLocalPath( | |
131 profile, | |
132 path, | |
133 base::Bind(&OpenFileWithMimeType, profile, path, url, callback)); | |
134 } | |
135 | |
136 // Called when execution of ContinueOpenItem() is completed. | |
137 void OnContinueOpenItemCompleted(Profile* profile, | |
138 const base::FilePath& file_path, | |
139 bool result) { | |
140 if (!result) { | |
141 int message; | |
142 if (file_path.Extension() == FILE_PATH_LITERAL(".dmg")) | |
143 message = IDS_FILE_BROWSER_ERROR_VIEWING_FILE_FOR_DMG; | |
144 else if (file_path.Extension() == FILE_PATH_LITERAL(".exe") || | |
145 file_path.Extension() == FILE_PATH_LITERAL(".msi")) | |
146 message = IDS_FILE_BROWSER_ERROR_VIEWING_FILE_FOR_EXECUTABLE; | |
147 else | |
148 message = IDS_FILE_BROWSER_ERROR_VIEWING_FILE; | |
149 ShowWarningMessageBox(profile, file_path, message); | |
150 } | |
151 } | |
152 | |
153 // Used to implement OpenItem(). | |
154 void ContinueOpenItem(Profile* profile, | 116 void ContinueOpenItem(Profile* profile, |
155 const base::FilePath& file_path, | 117 const base::FilePath& file_path, |
156 const GURL& url, | 118 const GURL& url, |
157 base::File::Error error) { | 119 platform_util::internal::OpenItemType expected_type, |
| 120 const platform_util::OpenOperationCallback& callback, |
| 121 base::File::Error error, |
| 122 const base::File::Info& file_info) { |
| 123 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 124 if (error != base::File::FILE_OK) { |
| 125 callback.Run(error == base::File::FILE_ERROR_NOT_FOUND |
| 126 ? platform_util::OPEN_FAILED_PATH_NOT_FOUND |
| 127 : platform_util::OPEN_FAILED_FILE_ERROR); |
| 128 return; |
| 129 } |
| 130 |
| 131 if (expected_type == platform_util::internal::OPEN_FOLDER && |
| 132 file_info.is_directory) { |
| 133 OpenFileManagerWithInternalActionId(profile, url, "open"); |
| 134 callback.Run(platform_util::OPEN_SUCCEEDED); |
| 135 return; |
| 136 } |
| 137 |
| 138 if (expected_type == platform_util::internal::OPEN_FILE && |
| 139 !file_info.is_directory) { |
| 140 extensions::app_file_handler_util::GetMimeTypeForLocalPath( |
| 141 profile, file_path, |
| 142 base::Bind(&OpenFileWithMimeType, profile, callback, file_path, url)); |
| 143 return; |
| 144 } |
| 145 |
| 146 callback.Run(platform_util::OPEN_FAILED_INVALID_TYPE); |
| 147 } |
| 148 |
| 149 void VerifyAndOpenItem(Profile* profile, |
| 150 const base::FilePath& file_path, |
| 151 platform_util::internal::OpenItemType expected_type, |
| 152 const platform_util::OpenOperationCallback& callback) { |
158 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 153 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
159 | 154 |
160 if (error == base::File::FILE_OK) { | 155 GURL url; |
161 // A directory exists at |url|. Open it with the file manager. | 156 if (!ConvertAbsoluteFilePathToFileSystemUrl(profile, file_path, |
162 OpenFileManagerWithInternalActionId(profile, url, "open"); | 157 kFileManagerAppId, &url)) { |
163 } else { | 158 callback.Run(platform_util::OPEN_FAILED_PATH_NOT_FOUND); |
164 // |url| should be a file. Open it. | 159 return; |
165 OpenFile(profile, | |
166 file_path, | |
167 url, | |
168 base::Bind(&OnContinueOpenItemCompleted, profile, file_path)); | |
169 } | 160 } |
170 } | |
171 | 161 |
172 // Converts the |path| passed from external callers to the filesystem URL | 162 GetMetadataForPath( |
173 // that the file manager can correctly handle. | 163 GetFileSystemContextForExtensionId(profile, kFileManagerAppId), url, |
174 // | 164 base::Bind(&ContinueOpenItem, profile, file_path, url, expected_type, |
175 // When conversion fails, it shows a warning dialog UI and returns false. | 165 callback)); |
176 bool ConvertPath(Profile* profile, const base::FilePath& path, GURL* url) { | |
177 if (!ConvertAbsoluteFilePathToFileSystemUrl( | |
178 profile, path, kFileManagerAppId, url)) { | |
179 ShowWarningMessageBox(profile, path, | |
180 IDS_FILE_BROWSER_ERROR_UNRESOLVABLE_FILE); | |
181 return false; | |
182 } | |
183 return true; | |
184 } | 166 } |
185 | 167 |
186 } // namespace | 168 } // namespace |
187 | 169 |
188 void OpenItem(Profile* profile, const base::FilePath& file_path) { | 170 void OpenFile(Profile* profile, |
| 171 const base::FilePath& file_path, |
| 172 const platform_util::OpenOperationCallback& callback) { |
| 173 VerifyAndOpenItem(profile, file_path, platform_util::internal::OPEN_FILE, |
| 174 callback); |
| 175 } |
| 176 |
| 177 void OpenFolder(Profile* profile, |
| 178 const base::FilePath& file_path, |
| 179 const platform_util::OpenOperationCallback& callback) { |
| 180 VerifyAndOpenItem(profile, file_path, platform_util::internal::OPEN_FOLDER, |
| 181 callback); |
| 182 } |
| 183 |
| 184 void ShowItemInFolder(Profile* profile, |
| 185 const base::FilePath& file_path, |
| 186 const platform_util::OpenOperationCallback& callback) { |
189 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 187 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
190 | 188 |
191 GURL url; | 189 GURL url; |
192 if (!ConvertPath(profile, file_path, &url)) | 190 if (!ConvertAbsoluteFilePathToFileSystemUrl(profile, file_path, |
| 191 kFileManagerAppId, &url)) { |
| 192 callback.Run(platform_util::OPEN_FAILED_PATH_NOT_FOUND); |
193 return; | 193 return; |
194 | 194 } |
195 CheckIfDirectoryExists( | |
196 GetFileSystemContextForExtensionId(profile, kFileManagerAppId), | |
197 url, | |
198 base::Bind(&ContinueOpenItem, profile, file_path, url)); | |
199 } | |
200 | |
201 void ShowItemInFolder(Profile* profile, const base::FilePath& file_path) { | |
202 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
203 | |
204 GURL url; | |
205 if (!ConvertPath(profile, file_path, &url)) | |
206 return; | |
207 | 195 |
208 // This action changes the selection so we do not reuse existing tabs. | 196 // This action changes the selection so we do not reuse existing tabs. |
209 OpenFileManagerWithInternalActionId(profile, url, "select"); | 197 OpenFileManagerWithInternalActionId(profile, url, "select"); |
| 198 callback.Run(platform_util::OPEN_SUCCEEDED); |
| 199 } |
| 200 |
| 201 void DisableShellOperationsForTesting() { |
| 202 shell_operations_allowed = false; |
210 } | 203 } |
211 | 204 |
212 } // namespace util | 205 } // namespace util |
213 } // namespace file_manager | 206 } // namespace file_manager |
OLD | NEW |