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 #include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h" | 4 #include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h" |
5 | 5 |
6 #include "ash/shell.h" | 6 #include "ash/shell.h" |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 GetSiteForExtensionId(kFileBrowserDomain); | 244 GetSiteForExtensionId(kFileBrowserDomain); |
245 fileapi::ExternalFileSystemBackend* backend = | 245 fileapi::ExternalFileSystemBackend* backend = |
246 BrowserContext::GetStoragePartitionForSite(profile, site)-> | 246 BrowserContext::GetStoragePartitionForSite(profile, site)-> |
247 GetFileSystemContext()->external_backend(); | 247 GetFileSystemContext()->external_backend(); |
248 if (!backend) | 248 if (!backend) |
249 return false; | 249 return false; |
250 backend->GrantFullAccessToExtension(GetFileBrowserUrl().host()); | 250 backend->GrantFullAccessToExtension(GetFileBrowserUrl().host()); |
251 return true; | 251 return true; |
252 } | 252 } |
253 | 253 |
254 // Executes handler specified with |task| for |url|. | 254 // Opens the file specified by |url| with |task|. |
255 void ExecuteHandler(Profile* profile, | 255 void OpenFileWithTask(Profile* profile, |
256 const file_tasks::TaskDescriptor& task, | 256 const file_tasks::TaskDescriptor& task, |
257 const GURL& url) { | 257 const GURL& url) { |
258 // If File Browser has not been open yet then it did not request access | 258 // If File Browser has not been open yet then it did not request access |
259 // to the file system. Do it now. | 259 // to the file system. Do it now. |
260 if (!GrantFileSystemAccessToFileBrowser(profile)) | 260 if (!GrantFileSystemAccessToFileBrowser(profile)) |
261 return; | 261 return; |
262 | 262 |
263 fileapi::FileSystemContext* file_system_context = | 263 fileapi::FileSystemContext* file_system_context = |
264 fileapi_util::GetFileSystemContextForExtensionId( | 264 fileapi_util::GetFileSystemContextForExtensionId( |
265 profile, kFileBrowserDomain); | 265 profile, kFileBrowserDomain); |
266 | 266 |
267 // We are executing the task on behalf of File Browser extension. | 267 // We are executing the task on behalf of File Browser extension. |
268 const GURL source_url = GetFileBrowserUrl(); | 268 const GURL source_url = GetFileBrowserUrl(); |
269 std::vector<FileSystemURL> urls; | 269 std::vector<FileSystemURL> urls; |
270 urls.push_back(file_system_context->CrackURL(url)); | 270 urls.push_back(file_system_context->CrackURL(url)); |
271 | 271 |
272 file_tasks::ExecuteFileTask( | 272 file_tasks::ExecuteFileTask( |
273 profile, | 273 profile, |
274 source_url, | 274 source_url, |
275 kFileBrowserDomain, | 275 kFileBrowserDomain, |
276 0, // no tab id | 276 0, // no tab id |
277 task, | 277 task, |
278 urls, | 278 urls, |
279 file_tasks::FileTaskFinishedCallback()); | 279 file_tasks::FileTaskFinishedCallback()); |
280 } | 280 } |
281 | 281 |
282 void OpenFileBrowserImpl(const base::FilePath& path, | 282 // Opens the file specified with |path|. Used to implement internal handlers |
283 const std::string& action_id) { | 283 // of special action IDs such as "auto-open", "open", and "select". |
| 284 void OpenFileWithInternalActionId(const base::FilePath& path, |
| 285 const std::string& action_id) { |
| 286 DCHECK(action_id == "auto-open" || |
| 287 action_id == "open" || |
| 288 action_id == "select"); |
| 289 |
284 content::RecordAction(UserMetricsAction("ShowFileBrowserFullTab")); | 290 content::RecordAction(UserMetricsAction("ShowFileBrowserFullTab")); |
285 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord(); | 291 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord(); |
286 | 292 |
287 GURL url; | 293 GURL url; |
288 if (!ConvertFileToFileSystemUrl(profile, path, kFileBrowserDomain, &url)) | 294 if (!ConvertFileToFileSystemUrl(profile, path, kFileBrowserDomain, &url)) |
289 return; | 295 return; |
290 | 296 |
291 file_tasks::TaskDescriptor task(kFileBrowserDomain, | 297 file_tasks::TaskDescriptor task(kFileBrowserDomain, |
292 file_tasks::kFileBrowserHandlerTaskType, | 298 file_tasks::kFileBrowserHandlerTaskType, |
293 action_id); | 299 action_id); |
294 ExecuteHandler(profile, task, url); | 300 OpenFileWithTask(profile, task, url); |
295 } | 301 } |
296 | 302 |
297 Browser* GetBrowserForUrl(GURL target_url) { | 303 Browser* GetBrowserForUrl(GURL target_url) { |
298 for (chrome::BrowserIterator it; !it.done(); it.Next()) { | 304 for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
299 Browser* browser = *it; | 305 Browser* browser = *it; |
300 TabStripModel* tab_strip = browser->tab_strip_model(); | 306 TabStripModel* tab_strip = browser->tab_strip_model(); |
301 for (int idx = 0; idx < tab_strip->count(); idx++) { | 307 for (int idx = 0; idx < tab_strip->count(); idx++) { |
302 content::WebContents* web_contents = tab_strip->GetWebContentsAt(idx); | 308 content::WebContents* web_contents = tab_strip->GetWebContentsAt(idx); |
303 const GURL& url = web_contents->GetLastCommittedURL(); | 309 const GURL& url = web_contents->GetLastCommittedURL(); |
304 if (url == target_url) | 310 if (url == target_url) |
305 return browser; | 311 return browser; |
306 } | 312 } |
307 } | 313 } |
308 return NULL; | 314 return NULL; |
309 } | 315 } |
310 | 316 |
311 bool ExecuteDefaultAppHandler(Profile* profile, | 317 // Opens the file specified by |path| and |url| with a file handler, |
| 318 // preferably the default handler for the type of the file. Returns false if |
| 319 // no file handler is found. |
| 320 bool OpenFileWithFileHandler(Profile* profile, |
312 const base::FilePath& path, | 321 const base::FilePath& path, |
313 const GURL& url, | 322 const GURL& url, |
314 const std::string& mime_type, | 323 const std::string& mime_type, |
315 const std::string& default_task_id) { | 324 const std::string& default_task_id) { |
316 ExtensionService* service = profile->GetExtensionService(); | 325 ExtensionService* service = profile->GetExtensionService(); |
317 if (!service) | 326 if (!service) |
318 return false; | 327 return false; |
319 | 328 |
320 PathAndMimeTypeSet files; | 329 PathAndMimeTypeSet files; |
321 files.insert(std::make_pair(path, mime_type)); | 330 files.insert(std::make_pair(path, mime_type)); |
(...skipping 24 matching lines...) Expand all Loading... |
346 i != file_handlers.end(); ++i) { | 355 i != file_handlers.end(); ++i) { |
347 const extensions::FileHandlerInfo* handler = *i; | 356 const extensions::FileHandlerInfo* handler = *i; |
348 std::string task_id = file_tasks::MakeTaskID( | 357 std::string task_id = file_tasks::MakeTaskID( |
349 extension->id(), | 358 extension->id(), |
350 file_tasks::kFileHandlerTaskType, | 359 file_tasks::kFileHandlerTaskType, |
351 handler->id); | 360 handler->id); |
352 if (task_id == default_task_id) { | 361 if (task_id == default_task_id) { |
353 file_tasks::TaskDescriptor task(extension->id(), | 362 file_tasks::TaskDescriptor task(extension->id(), |
354 file_tasks::kFileHandlerTaskType, | 363 file_tasks::kFileHandlerTaskType, |
355 handler->id); | 364 handler->id); |
356 ExecuteHandler(profile, task, url); | 365 OpenFileWithTask(profile, task, url); |
357 return true; | 366 return true; |
358 | 367 |
359 } else if (!first_handler) { | 368 } else if (!first_handler) { |
360 first_handler = handler; | 369 first_handler = handler; |
361 extension_for_first_handler = extension; | 370 extension_for_first_handler = extension; |
362 } | 371 } |
363 } | 372 } |
364 } | 373 } |
365 if (first_handler) { | 374 if (first_handler) { |
366 file_tasks::TaskDescriptor task(extension_for_first_handler->id(), | 375 file_tasks::TaskDescriptor task(extension_for_first_handler->id(), |
367 file_tasks::kFileHandlerTaskType, | 376 file_tasks::kFileHandlerTaskType, |
368 first_handler->id); | 377 first_handler->id); |
369 ExecuteHandler(profile, task, url); | 378 OpenFileWithTask(profile, task, url); |
370 return true; | 379 return true; |
371 } | 380 } |
372 return false; | 381 return false; |
373 } | 382 } |
374 | 383 |
375 bool ExecuteExtensionHandler(Profile* profile, | 384 // Returns true if |action_id| indicates that the file currently being |
376 const base::FilePath& path, | 385 // handled should be opened with the browser (i.e. should be opened with |
377 const FileBrowserHandler& handler, | 386 // OpenFileWithBrowser()). |
378 const GURL& url) { | 387 bool ShouldBeOpenedWithBrowser(const std::string& action_id) { |
| 388 return (action_id == "view-pdf" || |
| 389 action_id == "view-swf" || |
| 390 action_id == "view-in-browser" || |
| 391 action_id == "install-crx" || |
| 392 action_id == "open-hosted-generic" || |
| 393 action_id == "open-hosted-gdoc" || |
| 394 action_id == "open-hosted-gsheet" || |
| 395 action_id == "open-hosted-gslides"); |
| 396 } |
| 397 |
| 398 // Opens the file specified by |path| and |url| with the file browser handler |
| 399 // specified by |handler|. Returns false if failed to open the file. |
| 400 bool OpenFileWithFileBrowserHandler(Profile* profile, |
| 401 const base::FilePath& path, |
| 402 const FileBrowserHandler& handler, |
| 403 const GURL& url) { |
379 std::string extension_id = handler.extension_id(); | 404 std::string extension_id = handler.extension_id(); |
380 std::string action_id = handler.id(); | 405 std::string action_id = handler.id(); |
381 Browser* browser = chrome::FindLastActiveWithProfile(profile, | 406 Browser* browser = chrome::FindLastActiveWithProfile(profile, |
382 chrome::HOST_DESKTOP_TYPE_ASH); | 407 chrome::HOST_DESKTOP_TYPE_ASH); |
383 | 408 |
384 // If there is no browsers for the profile, bail out. Return true so warning | 409 // If there is no browsers for the profile, bail out. Return true so warning |
385 // about file type not being supported is not displayed. | 410 // about file type not being supported is not displayed. |
386 if (!browser) | 411 if (!browser) |
387 return true; | 412 return true; |
388 | 413 |
389 if (extension_id == kFileBrowserDomain) { | 414 // Some action IDs of the file manager's file browser handlers require the |
390 if (action_id == kFileBrowserGalleryTaskId || | 415 // file to be directly opened with the browser. |
391 action_id == kFileBrowserMountArchiveTaskId || | 416 if (extension_id == kFileBrowserDomain && |
392 action_id == kFileBrowserPlayTaskId || | 417 ShouldBeOpenedWithBrowser(action_id)) { |
393 action_id == kFileBrowserWatchTaskId) { | 418 return OpenFileWithBrowser(browser, path); |
394 file_tasks::TaskDescriptor task(extension_id, | |
395 file_tasks::kFileBrowserHandlerTaskType, | |
396 action_id); | |
397 ExecuteHandler(profile, task, url); | |
398 return true; | |
399 } | |
400 return ExecuteBuiltinHandler(browser, path); | |
401 } | 419 } |
402 | 420 |
403 file_tasks::TaskDescriptor task(extension_id, | 421 file_tasks::TaskDescriptor task(extension_id, |
404 file_tasks::kFileBrowserHandlerTaskType, | 422 file_tasks::kFileBrowserHandlerTaskType, |
405 action_id); | 423 action_id); |
406 ExecuteHandler(profile, task, url); | 424 OpenFileWithTask(profile, task, url); |
407 return true; | 425 return true; |
408 } | 426 } |
409 | 427 |
410 bool ExecuteDefaultHandler(Profile* profile, const base::FilePath& path) { | 428 // Opens the file specified by |path| with a handler (either of file browser |
| 429 // handler or file handler, preferably the default handler for the type of |
| 430 // the file), or opens the file with the browser. Returns false if failed to |
| 431 // open the file. |
| 432 bool OpenFileWithHandlerOrBrowser(Profile* profile, |
| 433 const base::FilePath& path) { |
411 GURL url; | 434 GURL url; |
412 if (!ConvertFileToFileSystemUrl(profile, path, kFileBrowserDomain, &url)) | 435 if (!ConvertFileToFileSystemUrl(profile, path, kFileBrowserDomain, &url)) |
413 return false; | 436 return false; |
414 | 437 |
415 std::string mime_type = GetMimeTypeForPath(path); | 438 std::string mime_type = GetMimeTypeForPath(path); |
416 std::string default_task_id = file_tasks::GetDefaultTaskIdFromPrefs( | 439 std::string default_task_id = file_tasks::GetDefaultTaskIdFromPrefs( |
417 profile, mime_type, path.Extension()); | 440 profile, mime_type, path.Extension()); |
418 | 441 |
419 // We choose the file handler from the following in decreasing priority or | 442 // We choose the file handler from the following in decreasing priority or |
420 // fail if none support the file type: | 443 // fail if none support the file type: |
421 // 1. default extension | 444 // 1. default file browser handler |
422 // 2. default app | 445 // 2. default file handler |
423 // 3. a fallback handler (e.g. opening in the browser) | 446 // 3. a fallback handler (e.g. opening in the browser) |
424 // 4. non-default app | 447 // 4. non-default file handler |
425 // 5. non-default extension | 448 // 5. non-default file browser handler |
426 // Note that there can be at most one of default extension and default app. | 449 // Note that there can be at most one of default extension and default app. |
427 const FileBrowserHandler* handler = | 450 const FileBrowserHandler* handler = |
428 file_browser_handlers::FindFileBrowserHandlerForURLAndPath( | 451 file_browser_handlers::FindFileBrowserHandlerForURLAndPath( |
429 profile, url, path); | 452 profile, url, path); |
430 if (!handler) { | 453 if (!handler) { |
431 return ExecuteDefaultAppHandler( | 454 return OpenFileWithFileHandler( |
432 profile, path, url, mime_type, default_task_id); | 455 profile, path, url, mime_type, default_task_id); |
433 } | 456 } |
434 | 457 |
435 std::string handler_task_id = file_tasks::MakeTaskID( | 458 std::string handler_task_id = file_tasks::MakeTaskID( |
436 handler->extension_id(), | 459 handler->extension_id(), |
437 file_tasks::kFileBrowserHandlerTaskType, | 460 file_tasks::kFileBrowserHandlerTaskType, |
438 handler->id()); | 461 handler->id()); |
439 if (handler_task_id != default_task_id && | 462 if (handler_task_id != default_task_id && |
440 !file_browser_handlers::IsFallbackFileBrowserHandler(handler) && | 463 !file_browser_handlers::IsFallbackFileBrowserHandler(handler) && |
441 ExecuteDefaultAppHandler( | 464 OpenFileWithFileHandler( |
442 profile, path, url, mime_type, default_task_id)) { | 465 profile, path, url, mime_type, default_task_id)) { |
443 return true; | 466 return true; |
444 } | 467 } |
445 return ExecuteExtensionHandler(profile, path, *handler, url); | 468 return OpenFileWithFileBrowserHandler(profile, path, *handler, url); |
446 } | 469 } |
447 | 470 |
448 // Reads the alternate URL from a GDoc file. When it fails, returns a file URL | 471 // Reads the alternate URL from a GDoc file. When it fails, returns a file URL |
449 // for |file_path| as fallback. | 472 // for |file_path| as fallback. |
450 // Note that an alternate url is a URL to open a hosted document. | 473 // Note that an alternate url is a URL to open a hosted document. |
451 GURL ReadUrlFromGDocOnBlockingPool(const base::FilePath& file_path) { | 474 GURL ReadUrlFromGDocOnBlockingPool(const base::FilePath& file_path) { |
452 GURL url = drive::util::ReadUrlFromGDocFile(file_path); | 475 GURL url = drive::util::ReadUrlFromGDocFile(file_path); |
453 if (url.is_empty()) | 476 if (url.is_empty()) |
454 url = net::FilePathToFileURL(file_path); | 477 url = net::FilePathToFileURL(file_path); |
455 return url; | 478 return url; |
456 } | 479 } |
457 | 480 |
458 // Used to implement ViewItem(). | 481 // Used to implement ViewItem(). |
459 void ContinueViewItem(Profile* profile, | 482 void ContinueViewItem(Profile* profile, |
460 const base::FilePath& path, | 483 const base::FilePath& path, |
461 base::PlatformFileError error) { | 484 base::PlatformFileError error) { |
462 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 485 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
463 | 486 |
464 if (error == base::PLATFORM_FILE_OK) { | 487 if (error == base::PLATFORM_FILE_OK) { |
465 // A directory exists at |path|. Open it with FileBrowser. | 488 // A directory exists at |path|. Open it with the file manager. |
466 OpenFileBrowserImpl(path, "open"); | 489 OpenFileWithInternalActionId(path, "open"); |
467 } else { | 490 } else { |
468 if (!ExecuteDefaultHandler(profile, path)) | 491 // |path| should be a file. Open it with a handler or the browser. |
| 492 if (!OpenFileWithHandlerOrBrowser(profile, path)) |
469 ShowWarningMessageBox(profile, path); | 493 ShowWarningMessageBox(profile, path); |
470 } | 494 } |
471 } | 495 } |
472 | 496 |
473 // Used to implement CheckIfDirectoryExists(). | 497 // Used to implement CheckIfDirectoryExists(). |
474 void CheckIfDirectoryExistsOnIOThread( | 498 void CheckIfDirectoryExistsOnIOThread( |
475 scoped_refptr<fileapi::FileSystemContext> file_system_context, | 499 scoped_refptr<fileapi::FileSystemContext> file_system_context, |
476 const GURL& url, | 500 const GURL& url, |
477 const fileapi::FileSystemOperationRunner::StatusCallback& callback) { | 501 const fileapi::FileSystemOperationRunner::StatusCallback& callback) { |
478 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 502 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
662 break; | 686 break; |
663 | 687 |
664 default: | 688 default: |
665 NOTREACHED(); | 689 NOTREACHED(); |
666 } | 690 } |
667 | 691 |
668 return title; | 692 return title; |
669 } | 693 } |
670 | 694 |
671 void ViewRemovableDrive(const base::FilePath& path) { | 695 void ViewRemovableDrive(const base::FilePath& path) { |
672 OpenFileBrowserImpl(path, "auto-open"); | 696 OpenFileWithInternalActionId(path, "auto-open"); |
673 } | 697 } |
674 | 698 |
675 void OpenActionChoiceDialog(const base::FilePath& path, bool advanced_mode) { | 699 void OpenActionChoiceDialog(const base::FilePath& path, bool advanced_mode) { |
676 const int kDialogWidth = 394; | 700 const int kDialogWidth = 394; |
677 // TODO(dgozman): remove 50, which is a title height once popup window | 701 // TODO(dgozman): remove 50, which is a title height once popup window |
678 // will have no title. | 702 // will have no title. |
679 const int kDialogHeight = 316 + 50; | 703 const int kDialogHeight = 316 + 50; |
680 | 704 |
681 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord(); | 705 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord(); |
682 | 706 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
732 scoped_refptr<fileapi::FileSystemContext> file_system_context = | 756 scoped_refptr<fileapi::FileSystemContext> file_system_context = |
733 fileapi_util::GetFileSystemContextForExtensionId( | 757 fileapi_util::GetFileSystemContextForExtensionId( |
734 profile, kFileBrowserDomain); | 758 profile, kFileBrowserDomain); |
735 | 759 |
736 CheckIfDirectoryExists(file_system_context, url, | 760 CheckIfDirectoryExists(file_system_context, url, |
737 base::Bind(&ContinueViewItem, profile, path)); | 761 base::Bind(&ContinueViewItem, profile, path)); |
738 } | 762 } |
739 | 763 |
740 void ShowFileInFolder(const base::FilePath& path) { | 764 void ShowFileInFolder(const base::FilePath& path) { |
741 // This action changes the selection so we do not reuse existing tabs. | 765 // This action changes the selection so we do not reuse existing tabs. |
742 OpenFileBrowserImpl(path, "select"); | 766 OpenFileWithInternalActionId(path, "select"); |
743 } | 767 } |
744 | 768 |
745 bool ExecuteBuiltinHandler(Browser* browser, const base::FilePath& path) { | 769 bool OpenFileWithBrowser(Browser* browser, const base::FilePath& path) { |
746 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 770 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
747 | 771 |
748 Profile* profile = browser->profile(); | 772 Profile* profile = browser->profile(); |
749 std::string file_extension = path.Extension(); | 773 std::string file_extension = path.Extension(); |
750 // For things supported natively by the browser, we should open it | 774 // For things supported natively by the browser, we should open it |
751 // in a tab. | 775 // in a tab. |
752 if (IsSupportedBrowserExtension(file_extension.data()) || | 776 if (IsSupportedBrowserExtension(file_extension.data()) || |
753 ShouldBeOpenedWithPlugin(profile, file_extension.data())) { | 777 ShouldBeOpenedWithPlugin(profile, file_extension.data())) { |
754 GURL page_url = net::FilePathToFileURL(path); | 778 GURL page_url = net::FilePathToFileURL(path); |
755 // Override drive resource to point to internal handler instead of file URL. | 779 // Override drive resource to point to internal handler instead of file URL. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
823 // determined, then indicate that it has the empty mime-type. This will | 847 // determined, then indicate that it has the empty mime-type. This will |
824 // only be matched if the Web Intents accepts "*" or "*/*". | 848 // only be matched if the Web Intents accepts "*" or "*/*". |
825 return ""; | 849 return ""; |
826 } else { | 850 } else { |
827 return mime_type; | 851 return mime_type; |
828 } | 852 } |
829 } | 853 } |
830 | 854 |
831 } // namespace util | 855 } // namespace util |
832 } // namespace file_manager | 856 } // namespace file_manager |
OLD | NEW |