| 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 |