Index: chrome/browser/chromeos/extensions/file_handler_util.cc |
diff --git a/chrome/browser/chromeos/extensions/file_handler_util.cc b/chrome/browser/chromeos/extensions/file_handler_util.cc |
index b3ad38411c3a273c591de9b395559a0bc2cfa14d..7780ae6c4a9f39e7691dce39a776b7936430618d 100644 |
--- a/chrome/browser/chromeos/extensions/file_handler_util.cc |
+++ b/chrome/browser/chromeos/extensions/file_handler_util.cc |
@@ -14,15 +14,18 @@ |
#include "chrome/browser/chromeos/gdata/gdata_util.h" |
#include "chrome/browser/chromeos/extensions/file_manager_util.h" |
#include "chrome/browser/extensions/extension_event_router.h" |
+#include "chrome/browser/extensions/extension_host.h" |
#include "chrome/browser/extensions/extension_service.h" |
#include "chrome/browser/extensions/extension_tab_util.h" |
#include "chrome/browser/prefs/scoped_user_pref_update.h" |
#include "chrome/browser/profiles/profile.h" |
#include "chrome/browser/ui/browser.h" |
+#include "chrome/common/chrome_notification_types.h" |
#include "chrome/common/extensions/file_browser_handler.h" |
#include "chrome/common/pref_names.h" |
#include "content/public/browser/browser_thread.h" |
#include "content/public/browser/child_process_security_policy.h" |
+#include "content/public/browser/notification_service.h" |
#include "content/public/browser/render_process_host.h" |
#include "content/public/browser/site_instance.h" |
#include "content/public/browser/web_contents.h" |
@@ -449,11 +452,6 @@ class FileTaskExecutor::ExecuteTasksFileSystemCallbackDispatcher { |
} |
} |
- ChildProcessSecurityPolicy::GetInstance()->GrantPermissionsForFile( |
- handler_pid_, |
- final_file_path, |
- GetAccessPermissionsForHandler(handler_extension_.get(), action_id_)); |
- |
// Grant access to this particular file to target extension. This will |
// ensure that the target extension can access only this FS entry and |
// prevent from traversing FS hierarchy upward. |
@@ -491,8 +489,8 @@ FileTaskExecutor::FileTaskExecutor(Profile* profile, |
: profile_(profile), |
source_url_(source_url), |
extension_id_(extension_id), |
- action_id_(action_id) |
-{} |
+ action_id_(action_id) { |
+} |
FileTaskExecutor::~FileTaskExecutor() {} |
@@ -508,8 +506,11 @@ bool FileTaskExecutor::Execute(const std::vector<GURL>& file_urls) { |
return false; |
int handler_pid = ExtractProcessFromExtensionId(handler->id(), profile_); |
- if (handler_pid < 0) |
- return false; |
+ if (handler_pid <= 0) { |
+ if (!handler->has_lazy_background_page()) |
+ return false; |
+ RegisterNotificationObservers(); |
+ } |
// Get local file system instance on file thread. |
BrowserThread::PostTask( |
@@ -547,21 +548,6 @@ void FileTaskExecutor::ExecuteFailedOnUIThread() { |
Done(false); |
} |
-void FileTaskExecutor::SetupFileAccessPermissionsForGDataCache( |
- const FileDefinitionList& file_list, |
- int handler_pid) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- for (FileDefinitionList::const_iterator iter = file_list.begin(); |
- iter != file_list.end(); |
- ++iter) { |
- if (!gdata::util::IsUnderGDataMountPoint(iter->absolute_path)) |
- continue; |
- gdata::util::SetPermissionsForGDataCacheFiles(profile_, handler_pid, |
- iter->absolute_path); |
- } |
-} |
- |
void FileTaskExecutor::ExecuteFileActionsOnUIThread( |
const std::string& file_system_name, |
const GURL& file_system_root, |
@@ -587,7 +573,10 @@ void FileTaskExecutor::ExecuteFileActionsOnUIThread( |
return; |
} |
- SetupFileAccessPermissionsForGDataCache(file_list, handler_pid); |
+ InitHandlerHostFileAccessPermissions(file_list, extension, action_id_); |
+ |
+ if (handler_pid > 0) |
+ SetupHandlerHostFileAccessPermissions(handler_pid); |
scoped_ptr<ListValue> event_args(new ListValue()); |
event_args->Append(Value::CreateStringValue(action_id_)); |
@@ -623,7 +612,89 @@ void FileTaskExecutor::ExecuteFileActionsOnUIThread( |
extension_id_, std::string("fileBrowserHandler.onExecute"), |
json_args, profile_, |
GURL()); |
- Done(true); |
+ |
+ // If we don't have handler process id, we'll have to wait until the |
+ // background host loads so we can setup file access permissions. |
+ if (handler_pid > 0) |
+ Done(true); |
+} |
+ |
+void FileTaskExecutor::InitHandlerHostFileAccessPermissions( |
+ const FileDefinitionList& file_list, |
+ const Extension* handler_extension, |
+ const std::string& action_id) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
+ for (FileDefinitionList::const_iterator iter = file_list.begin(); |
+ iter != file_list.end(); |
+ ++iter) { |
+ // Setup permission for file's absolute file. |
+ handler_host_permissions_.push_back(std::make_pair( |
+ iter->absolute_path, |
+ GetAccessPermissionsForHandler(handler_extension, action_id))); |
+ |
+ if (!gdata::util::IsUnderGDataMountPoint(iter->absolute_path)) |
+ continue; |
+ |
+ // If the file is on gdata mount point, we'll have to give handler host |
+ // permissions for file's gdata cache paths. |
+ // This has to be called on UI thread. |
+ gdata::util::InsertGDataCachePathsPermissions(profile_, iter->absolute_path, |
+ &handler_host_permissions_); |
+ } |
+} |
+ |
+void FileTaskExecutor::SetupHandlerHostFileAccessPermissions(int handler_pid) { |
+ for (size_t i = 0; i < handler_host_permissions_.size(); i++) { |
+ content::ChildProcessSecurityPolicy::GetInstance()->GrantPermissionsForFile( |
+ handler_pid, |
+ handler_host_permissions_[i].first, |
+ handler_host_permissions_[i].second); |
+ } |
+ |
+ // We don't need this anymore. |
+ handler_host_permissions_.clear(); |
+} |
+ |
+void FileTaskExecutor::RegisterNotificationObservers() { |
+ // We should do this only once. |
+ 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
|
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, |
+ content::NotificationService::AllBrowserContextsAndSources()); |
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
+ content::Source<Profile>(profile_)); |
+} |
+ |
+void FileTaskExecutor::Observe( |
+ int type, |
+ const content::NotificationSource& source, |
+ const content::NotificationDetails& details) { |
+ switch (type) { |
+ case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: { |
+ ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); |
+ if (host->profile()->IsSameProfile(profile_) && |
+ host->extension()->id() == extension_id_) { |
+ CHECK(host->did_stop_loading()); |
+ DCHECK(host->extension()->has_lazy_background_page()); |
+ |
+ SetupHandlerHostFileAccessPermissions( |
+ host->render_process_host()->GetID()); |
+ Done(true); |
+ break; |
+ } |
+ } |
+ case chrome::NOTIFICATION_EXTENSION_UNLOADED: { |
+ UnloadedExtensionInfo* unloaded = |
+ content::Details<UnloadedExtensionInfo>(details).ptr(); |
+ 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
|
+ Done(false); |
+ break; |
+ } |
+ } |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
} |
} // namespace file_handler_util |