Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: chrome/browser/chromeos/extensions/file_handler_util.cc

Issue 10067021: Postpone setting up file handler's file permissions if handler is running lazy background page. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/extensions/file_handler_util.h" 5 #include "chrome/browser/chromeos/extensions/file_handler_util.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/file_util.h" 8 #include "base/file_util.h"
9 #include "base/i18n/case_conversion.h" 9 #include "base/i18n/case_conversion.h"
10 #include "base/json/json_writer.h" 10 #include "base/json/json_writer.h"
11 #include "base/string_util.h" 11 #include "base/string_util.h"
12 #include "base/stringprintf.h" 12 #include "base/stringprintf.h"
13 #include "base/utf_string_conversions.h" 13 #include "base/utf_string_conversions.h"
14 #include "chrome/browser/chromeos/gdata/gdata_util.h" 14 #include "chrome/browser/chromeos/gdata/gdata_util.h"
15 #include "chrome/browser/chromeos/extensions/file_manager_util.h" 15 #include "chrome/browser/chromeos/extensions/file_manager_util.h"
16 #include "chrome/browser/extensions/extension_event_router.h" 16 #include "chrome/browser/extensions/extension_event_router.h"
17 #include "chrome/browser/extensions/extension_host.h"
17 #include "chrome/browser/extensions/extension_service.h" 18 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/extensions/extension_tab_util.h" 19 #include "chrome/browser/extensions/extension_tab_util.h"
19 #include "chrome/browser/prefs/scoped_user_pref_update.h" 20 #include "chrome/browser/prefs/scoped_user_pref_update.h"
20 #include "chrome/browser/profiles/profile.h" 21 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/ui/browser.h" 22 #include "chrome/browser/ui/browser.h"
23 #include "chrome/common/chrome_notification_types.h"
22 #include "chrome/common/extensions/file_browser_handler.h" 24 #include "chrome/common/extensions/file_browser_handler.h"
23 #include "chrome/common/pref_names.h" 25 #include "chrome/common/pref_names.h"
24 #include "content/public/browser/browser_thread.h" 26 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/child_process_security_policy.h" 27 #include "content/public/browser/child_process_security_policy.h"
28 #include "content/public/browser/notification_service.h"
26 #include "content/public/browser/render_process_host.h" 29 #include "content/public/browser/render_process_host.h"
27 #include "content/public/browser/site_instance.h" 30 #include "content/public/browser/site_instance.h"
28 #include "content/public/browser/web_contents.h" 31 #include "content/public/browser/web_contents.h"
29 #include "net/base/escape.h" 32 #include "net/base/escape.h"
30 #include "webkit/fileapi/file_system_context.h" 33 #include "webkit/fileapi/file_system_context.h"
31 #include "webkit/fileapi/file_system_mount_point_provider.h" 34 #include "webkit/fileapi/file_system_mount_point_provider.h"
32 #include "webkit/fileapi/file_system_util.h" 35 #include "webkit/fileapi/file_system_util.h"
33 36
34 using content::BrowserContext; 37 using content::BrowserContext;
35 using content::BrowserThread; 38 using content::BrowserThread;
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 // If the file is under gdata mount point, there is no actual file to be 445 // If the file is under gdata mount point, there is no actual file to be
443 // found on the final_file_path. 446 // found on the final_file_path.
444 if (!is_gdata_file) { 447 if (!is_gdata_file) {
445 if (!file_util::PathExists(final_file_path) || 448 if (!file_util::PathExists(final_file_path) ||
446 file_util::IsLink(final_file_path) || 449 file_util::IsLink(final_file_path) ||
447 !file_util::GetFileInfo(final_file_path, &file_info)) { 450 !file_util::GetFileInfo(final_file_path, &file_info)) {
448 return false; 451 return false;
449 } 452 }
450 } 453 }
451 454
452 ChildProcessSecurityPolicy::GetInstance()->GrantPermissionsForFile(
453 handler_pid_,
454 final_file_path,
455 GetAccessPermissionsForHandler(handler_extension_.get(), action_id_));
456
457 // Grant access to this particular file to target extension. This will 455 // Grant access to this particular file to target extension. This will
458 // ensure that the target extension can access only this FS entry and 456 // ensure that the target extension can access only this FS entry and
459 // prevent from traversing FS hierarchy upward. 457 // prevent from traversing FS hierarchy upward.
460 external_provider->GrantFileAccessToExtension(handler_extension_->id(), 458 external_provider->GrantFileAccessToExtension(handler_extension_->id(),
461 virtual_path); 459 virtual_path);
462 460
463 // Output values. 461 // Output values.
464 GURL target_origin_url(Extension::GetBaseURLFromExtensionId( 462 GURL target_origin_url(Extension::GetBaseURLFromExtensionId(
465 handler_extension_->id())); 463 handler_extension_->id()));
466 GURL base_url = fileapi::GetFileSystemRootURI(target_origin_url, 464 GURL base_url = fileapi::GetFileSystemRootURI(target_origin_url,
(...skipping 17 matching lines...) Expand all
484 DISALLOW_COPY_AND_ASSIGN(ExecuteTasksFileSystemCallbackDispatcher); 482 DISALLOW_COPY_AND_ASSIGN(ExecuteTasksFileSystemCallbackDispatcher);
485 }; 483 };
486 484
487 FileTaskExecutor::FileTaskExecutor(Profile* profile, 485 FileTaskExecutor::FileTaskExecutor(Profile* profile,
488 const GURL source_url, 486 const GURL source_url,
489 const std::string& extension_id, 487 const std::string& extension_id,
490 const std::string& action_id) 488 const std::string& action_id)
491 : profile_(profile), 489 : profile_(profile),
492 source_url_(source_url), 490 source_url_(source_url),
493 extension_id_(extension_id), 491 extension_id_(extension_id),
494 action_id_(action_id) 492 action_id_(action_id) {
495 {} 493 }
496 494
497 FileTaskExecutor::~FileTaskExecutor() {} 495 FileTaskExecutor::~FileTaskExecutor() {}
498 496
499 bool FileTaskExecutor::Execute(const std::vector<GURL>& file_urls) { 497 bool FileTaskExecutor::Execute(const std::vector<GURL>& file_urls) {
500 ExtensionService* service = profile_->GetExtensionService(); 498 ExtensionService* service = profile_->GetExtensionService();
501 if (!service) 499 if (!service)
502 return false; 500 return false;
503 501
504 scoped_refptr<const Extension> handler = 502 scoped_refptr<const Extension> handler =
505 service->GetExtensionById(extension_id_, false); 503 service->GetExtensionById(extension_id_, false);
506 504
507 if (!handler.get()) 505 if (!handler.get())
508 return false; 506 return false;
509 507
510 int handler_pid = ExtractProcessFromExtensionId(handler->id(), profile_); 508 int handler_pid = ExtractProcessFromExtensionId(handler->id(), profile_);
511 if (handler_pid < 0) 509 if (handler_pid <= 0) {
512 return false; 510 if (!handler->has_lazy_background_page())
511 return false;
512 RegisterNotificationObservers();
513 }
513 514
514 // Get local file system instance on file thread. 515 // Get local file system instance on file thread.
515 BrowserThread::PostTask( 516 BrowserThread::PostTask(
516 BrowserThread::FILE, FROM_HERE, 517 BrowserThread::FILE, FROM_HERE,
517 base::Bind( 518 base::Bind(
518 &FileTaskExecutor::RequestFileEntryOnFileThread, 519 &FileTaskExecutor::RequestFileEntryOnFileThread,
519 this, 520 this,
520 Extension::GetBaseURLFromExtensionId(handler->id()), 521 Extension::GetBaseURLFromExtensionId(handler->id()),
521 handler, 522 handler,
522 handler_pid, 523 handler_pid,
(...skipping 17 matching lines...) Expand all
540 handler, 541 handler,
541 handler_pid, 542 handler_pid,
542 action_id_, 543 action_id_,
543 file_urls)); 544 file_urls));
544 } 545 }
545 546
546 void FileTaskExecutor::ExecuteFailedOnUIThread() { 547 void FileTaskExecutor::ExecuteFailedOnUIThread() {
547 Done(false); 548 Done(false);
548 } 549 }
549 550
550 void FileTaskExecutor::SetupFileAccessPermissionsForGDataCache(
551 const FileDefinitionList& file_list,
552 int handler_pid) {
553 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
554
555 for (FileDefinitionList::const_iterator iter = file_list.begin();
556 iter != file_list.end();
557 ++iter) {
558 if (!gdata::util::IsUnderGDataMountPoint(iter->absolute_path))
559 continue;
560 gdata::util::SetPermissionsForGDataCacheFiles(profile_, handler_pid,
561 iter->absolute_path);
562 }
563 }
564
565 void FileTaskExecutor::ExecuteFileActionsOnUIThread( 551 void FileTaskExecutor::ExecuteFileActionsOnUIThread(
566 const std::string& file_system_name, 552 const std::string& file_system_name,
567 const GURL& file_system_root, 553 const GURL& file_system_root,
568 const FileDefinitionList& file_list, 554 const FileDefinitionList& file_list,
569 int handler_pid) { 555 int handler_pid) {
570 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 556 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
571 557
572 ExtensionService* service = profile_->GetExtensionService(); 558 ExtensionService* service = profile_->GetExtensionService();
573 if (!service) { 559 if (!service) {
574 Done(false); 560 Done(false);
575 return; 561 return;
576 } 562 }
577 563
578 const Extension* extension = service->GetExtensionById(extension_id_, false); 564 const Extension* extension = service->GetExtensionById(extension_id_, false);
579 if (!extension) { 565 if (!extension) {
580 Done(false); 566 Done(false);
581 return; 567 return;
582 } 568 }
583 569
584 ExtensionEventRouter* event_router = profile_->GetExtensionEventRouter(); 570 ExtensionEventRouter* event_router = profile_->GetExtensionEventRouter();
585 if (!event_router) { 571 if (!event_router) {
586 Done(false); 572 Done(false);
587 return; 573 return;
588 } 574 }
589 575
590 SetupFileAccessPermissionsForGDataCache(file_list, handler_pid); 576 InitHandlerHostFileAccessPermissions(file_list, extension, action_id_);
577
578 if (handler_pid > 0)
579 SetupHandlerHostFileAccessPermissions(handler_pid);
591 580
592 scoped_ptr<ListValue> event_args(new ListValue()); 581 scoped_ptr<ListValue> event_args(new ListValue());
593 event_args->Append(Value::CreateStringValue(action_id_)); 582 event_args->Append(Value::CreateStringValue(action_id_));
594 DictionaryValue* details = new DictionaryValue(); 583 DictionaryValue* details = new DictionaryValue();
595 event_args->Append(details); 584 event_args->Append(details);
596 // Get file definitions. These will be replaced with Entry instances by 585 // Get file definitions. These will be replaced with Entry instances by
597 // chromeHidden.Event.dispatchJSON() method from even_binding.js. 586 // chromeHidden.Event.dispatchJSON() method from even_binding.js.
598 ListValue* files_urls = new ListValue(); 587 ListValue* files_urls = new ListValue();
599 details->Set("entries", files_urls); 588 details->Set("entries", files_urls);
600 for (FileDefinitionList::const_iterator iter = file_list.begin(); 589 for (FileDefinitionList::const_iterator iter = file_list.begin();
(...skipping 15 matching lines...) Expand all
616 } 605 }
617 606
618 UpdateFileHandlerUsageStats(profile_, MakeTaskID(extension_id_, action_id_)); 607 UpdateFileHandlerUsageStats(profile_, MakeTaskID(extension_id_, action_id_));
619 608
620 std::string json_args; 609 std::string json_args;
621 base::JSONWriter::Write(event_args.get(), &json_args); 610 base::JSONWriter::Write(event_args.get(), &json_args);
622 event_router->DispatchEventToExtension( 611 event_router->DispatchEventToExtension(
623 extension_id_, std::string("fileBrowserHandler.onExecute"), 612 extension_id_, std::string("fileBrowserHandler.onExecute"),
624 json_args, profile_, 613 json_args, profile_,
625 GURL()); 614 GURL());
626 Done(true); 615
616 // If we don't have handler process id, we'll have to wait until the
617 // background host loads so we can setup file access permissions.
618 if (handler_pid > 0)
619 Done(true);
620 }
621
622 void FileTaskExecutor::InitHandlerHostFileAccessPermissions(
623 const FileDefinitionList& file_list,
624 const Extension* handler_extension,
625 const std::string& action_id) {
626 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
627
628 for (FileDefinitionList::const_iterator iter = file_list.begin();
629 iter != file_list.end();
630 ++iter) {
631 // Setup permission for file's absolute file.
632 handler_host_permissions_.push_back(std::make_pair(
633 iter->absolute_path,
634 GetAccessPermissionsForHandler(handler_extension, action_id)));
635
636 if (!gdata::util::IsUnderGDataMountPoint(iter->absolute_path))
637 continue;
638
639 // If the file is on gdata mount point, we'll have to give handler host
640 // permissions for file's gdata cache paths.
641 // This has to be called on UI thread.
642 gdata::util::InsertGDataCachePathsPermissions(profile_, iter->absolute_path,
643 &handler_host_permissions_);
644 }
645 }
646
647 void FileTaskExecutor::SetupHandlerHostFileAccessPermissions(int handler_pid) {
648 for (size_t i = 0; i < handler_host_permissions_.size(); i++) {
649 content::ChildProcessSecurityPolicy::GetInstance()->GrantPermissionsForFile(
650 handler_pid,
651 handler_host_permissions_[i].first,
652 handler_host_permissions_[i].second);
653 }
654
655 // We don't need this anymore.
656 handler_host_permissions_.clear();
657 }
658
659 void FileTaskExecutor::RegisterNotificationObservers() {
660 // We should do this only once.
661 DCHECK(registrar_.IsEmpty());
dgozman 2012/04/13 12:41:04 Don't we need to unregister observers?
tbarzic 2012/04/13 16:07:58 Not really. They will get unregistered when the ob
662 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
663 content::NotificationService::AllBrowserContextsAndSources());
664 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
665 content::Source<Profile>(profile_));
666 }
667
668 void FileTaskExecutor::Observe(
669 int type,
670 const content::NotificationSource& source,
671 const content::NotificationDetails& details) {
672 switch (type) {
673 case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: {
674 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
675 if (host->profile()->IsSameProfile(profile_) &&
676 host->extension()->id() == extension_id_) {
677 CHECK(host->did_stop_loading());
678 DCHECK(host->extension()->has_lazy_background_page());
679
680 SetupHandlerHostFileAccessPermissions(
681 host->render_process_host()->GetID());
682 Done(true);
683 break;
684 }
685 }
686 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
687 UnloadedExtensionInfo* unloaded =
688 content::Details<UnloadedExtensionInfo>(details).ptr();
689 if (unloaded->extension->id() == extension_id_) {
dgozman 2012/04/13 12:41:04 Why don't we check profile here (as above)?
tbarzic 2012/04/13 16:07:58 NOTIFICATION_EXTENSION_UNLOADED has registered onl
690 Done(false);
691 break;
692 }
693 }
694 default:
695 NOTREACHED();
696 break;
697 }
627 } 698 }
628 699
629 } // namespace file_handler_util 700 } // namespace file_handler_util
630 701
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698