diff options
-rw-r--r-- | chrome/browser/extensions/extensions_service.cc | 50 | ||||
-rw-r--r-- | chrome/browser/net/chrome_url_request_context.cc | 40 | ||||
-rw-r--r-- | chrome/browser/net/chrome_url_request_context.h | 8 | ||||
-rw-r--r-- | chrome/browser/notifications/desktop_notification_service.cc | 31 | ||||
-rw-r--r-- | chrome/browser/notifications/desktop_notification_service.h | 10 | ||||
-rw-r--r-- | chrome/browser/profile.cc | 60 | ||||
-rw-r--r-- | chrome/browser/profile.h | 14 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.cc | 18 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.h | 1 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 3 | ||||
-rw-r--r-- | chrome/renderer/notification_provider.cc | 3 | ||||
-rw-r--r-- | chrome/renderer/notification_provider.h | 2 | ||||
-rw-r--r-- | webkit/database/database_tracker.cc | 5 | ||||
-rw-r--r-- | webkit/database/database_tracker.h | 1 |
14 files changed, 137 insertions, 109 deletions
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index 50d48d2..b56d5b6 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -578,29 +578,14 @@ void ExtensionsService::LoadInstalledExtension(const ExtensionInfo& info, } void ExtensionsService::NotifyExtensionLoaded(Extension* extension) { - LOG(INFO) << "Sending EXTENSION_LOADED"; - - // The ChromeURLRequestContext needs to be first to know that the extension + // The ChromeURLRequestContexts need to be first to know that the extension // was loaded, otherwise a race can arise where a renderer that is created // for the extension may try to load an extension URL with an extension id - // that the request context doesn't yet know about. - if (profile_ && !profile_->IsOffTheRecord()) { - ChromeURLRequestContextGetter* context_getter = - static_cast<ChromeURLRequestContextGetter*>( - profile_->GetRequestContext()); - if (context_getter) { - ChromeThread::PostTask( - ChromeThread::IO, FROM_HERE, - NewRunnableMethod( - context_getter, - &ChromeURLRequestContextGetter::OnNewExtensions, - extension->id(), - new ChromeURLRequestContext::ExtensionInfo( - extension->path(), - extension->default_locale(), - std::vector<URLPattern>(), - extension->api_permissions()))); - } + // that the request context doesn't yet know about. The profile is responsible + // for ensuring its URLRequestContexts appropriately discover the loaded + // extension. + if (profile_) { + profile_->RegisterExtensionWithRequestContexts(extension); // Check if this permission requires unlimited storage quota if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) { @@ -616,6 +601,8 @@ void ExtensionsService::NotifyExtensionLoaded(Extension* extension) { } } + LOG(INFO) << "Sending EXTENSION_LOADED"; + NotificationService::current()->Notify( NotificationType::EXTENSION_LOADED, Source<Profile>(profile_), @@ -630,17 +617,20 @@ void ExtensionsService::NotifyExtensionUnloaded(Extension* extension) { Source<Profile>(profile_), Details<Extension>(extension)); - if (profile_ && !profile_->IsOffTheRecord()) { - ChromeURLRequestContextGetter* context_getter = - static_cast<ChromeURLRequestContextGetter*>( - profile_->GetRequestContext()); - if (context_getter) { + if (profile_) { + profile_->UnregisterExtensionWithRequestContexts(extension); + + // Check if this permission required unlimited storage quota, reset its + // in-memory quota. + if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) { + string16 origin_identifier = + webkit_database::DatabaseUtil::GetOriginIdentifier(extension->url()); ChromeThread::PostTask( - ChromeThread::IO, FROM_HERE, + ChromeThread::FILE, FROM_HERE, NewRunnableMethod( - context_getter, - &ChromeURLRequestContextGetter::OnUnloadedExtension, - extension->id())); + profile_->GetDatabaseTracker(), + &webkit_database::DatabaseTracker::ResetOriginQuotaInMemory, + origin_identifier)); } } } diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc index be1e63b..101e0c2 100644 --- a/chrome/browser/net/chrome_url_request_context.cc +++ b/chrome/browser/net/chrome_url_request_context.cc @@ -748,32 +748,28 @@ std::string ChromeURLRequestContext::GetDefaultLocaleForExtension( bool ChromeURLRequestContext::CheckURLAccessToExtensionPermission( const GURL& url, - const std::string& application_id, const char* permission_name) { - DCHECK(!application_id.empty()); + ExtensionInfoMap::iterator info; + if (url.SchemeIs(chrome::kExtensionScheme)) { + // If the url is an extension scheme, we just look it up by extension id. + std::string id = url.host(); + info = extension_info_.find(id); + } else { + // Otherwise, we scan for a matching extent. Overlapping extents are + // disallowed, so only one will match. + info = extension_info_.begin(); + while (info != extension_info_.end() && + !info->second->extent.ContainsURL(url)) + ++info; + } - // Get the information about the specified extension. If the extension isn't - // installed, then permission is not granted. - ExtensionInfoMap::iterator info = extension_info_.find(application_id); if (info == extension_info_.end()) return false; - // Check that the extension declares the required permission. - std::vector<std::string>& permissions = info->second->api_permissions; - if (permissions.end() == std::find(permissions.begin(), permissions.end(), - permission_name)) { - return false; - } - - // Check that the extension declares the source URL in its extent. - Extension::URLPatternList& extent = info->second->extent; - for (Extension::URLPatternList::iterator pattern = extent.begin(); - pattern != extent.end(); ++pattern) { - if (pattern->MatchesUrl(url)) - return true; - } - - return false; + std::vector<std::string>& api_permissions = info->second->api_permissions; + return std::find(api_permissions.begin(), + api_permissions.end(), + permission_name) != api_permissions.end(); } const std::string& ChromeURLRequestContext::GetUserAgent( @@ -945,7 +941,7 @@ ChromeURLRequestContextFactory::ChromeURLRequestContextFactory(Profile* profile) new ChromeURLRequestContext::ExtensionInfo( (*iter)->path(), (*iter)->default_locale(), - std::vector<URLPattern>(), + (*iter)->web_extent(), (*iter)->api_permissions())); } } diff --git a/chrome/browser/net/chrome_url_request_context.h b/chrome/browser/net/chrome_url_request_context.h index d483600..ae49a5c 100644 --- a/chrome/browser/net/chrome_url_request_context.h +++ b/chrome/browser/net/chrome_url_request_context.h @@ -44,14 +44,14 @@ class ChromeURLRequestContext : public URLRequestContext { // both threads. There is only a small amount of mutable state in Extension. struct ExtensionInfo { ExtensionInfo(const FilePath& path, const std::string& default_locale, - const Extension::URLPatternList& extent, + const ExtensionExtent& extent, const std::vector<std::string>& api_permissions) : path(path), default_locale(default_locale), extent(extent), api_permissions(api_permissions) { } FilePath path; std::string default_locale; - Extension::URLPatternList extent; + ExtensionExtent extent; std::vector<std::string> api_permissions; }; @@ -68,11 +68,7 @@ class ChromeURLRequestContext : public URLRequestContext { std::string GetDefaultLocaleForExtension(const std::string& id); // Determine whether a URL has access to the specified extension permission. - // TODO(aa): This will eventually have to take an additional parameter: the - // ID of a specific extension to check, since |url| could show up in multiple - // extensions. bool CheckURLAccessToExtensionPermission(const GURL& url, - const std::string& application_id, const char* permission_name); // Gets the path to the directory user scripts are stored in. diff --git a/chrome/browser/notifications/desktop_notification_service.cc b/chrome/browser/notifications/desktop_notification_service.cc index d351880..aa769d3 100644 --- a/chrome/browser/notifications/desktop_notification_service.cc +++ b/chrome/browser/notifications/desktop_notification_service.cc @@ -194,11 +194,6 @@ DesktopNotificationService::DesktopNotificationService(Profile* profile, : profile_(profile), ui_manager_(ui_manager) { InitPrefs(); - - // Listen for new extension installations so we can cache permissions. - notification_registrar_.Add(this, - NotificationType::EXTENSION_LOADED, - Source<Profile>(profile_)); } DesktopNotificationService::~DesktopNotificationService() { @@ -222,35 +217,9 @@ void DesktopNotificationService::InitPrefs() { } prefs_cache_ = new NotificationsPrefsCache(allowed_sites, denied_sites); - - ExtensionsService* ext_service = profile_->GetExtensionsService(); - if (ext_service) { - const ExtensionList* extensions = ext_service->extensions(); - for (ExtensionList::const_iterator iter = extensions->begin(); - iter != extensions->end(); ++iter) { - if ((*iter)->HasApiPermission(Extension::kNotificationPermission)) { - prefs_cache_->CacheAllowedOrigin((*iter)->url()); - } - } - } - prefs_cache_->set_is_initialized(true); } -void DesktopNotificationService::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (type != NotificationType::EXTENSION_LOADED) { - NOTREACHED(); - return; - } - - Details<Extension> extension = static_cast<Details<Extension> >(details); - if (extension->HasApiPermission(Extension::kNotificationPermission)) { - GrantPermission(extension->url()); - } -} - void DesktopNotificationService::GrantPermission(const GURL& origin) { DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); PersistPermissionChange(origin, true); diff --git a/chrome/browser/notifications/desktop_notification_service.h b/chrome/browser/notifications/desktop_notification_service.h index 6e9a6d8..8be6f85 100644 --- a/chrome/browser/notifications/desktop_notification_service.h +++ b/chrome/browser/notifications/desktop_notification_service.h @@ -21,7 +21,7 @@ class Task; // The DesktopNotificationService is an object, owned by the Profile, // which provides the creation of desktop "toasts" to web pages and workers. -class DesktopNotificationService : public NotificationObserver { +class DesktopNotificationService { public: enum DesktopNotificationSource { PageNotification, @@ -71,11 +71,6 @@ class DesktopNotificationService : public NotificationObserver { NotificationsPrefsCache* prefs_cache() { return prefs_cache_; } - // NotificationObserver interface. - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - // Creates a data:xxxx URL which contains the full HTML for a notification // using supplied icon, title, and text, run through a template which contains // the standard formatting for notifications. @@ -103,9 +98,6 @@ class DesktopNotificationService : public NotificationObserver { // UI for desktop toasts. NotificationUIManager* ui_manager_; - // Connection to the service providing the other kind of notifications. - NotificationRegistrar notification_registrar_; - DISALLOW_COPY_AND_ASSIGN(DesktopNotificationService); }; diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc index 7287f26..c808574 100644 --- a/chrome/browser/profile.cc +++ b/chrome/browser/profile.cc @@ -130,6 +130,34 @@ bool HasACacheSubdir(const FilePath &dir) { file_util::PathExists(GetMediaCachePath(dir)); } +void PostExtensionLoadedToContextGetter(ChromeURLRequestContextGetter* getter, + Extension* extension) { + if (!getter) + return; + // Callee takes ownership of new ExtensionInfo struct. + ChromeThread::PostTask( + ChromeThread::IO, FROM_HERE, + NewRunnableMethod(getter, + &ChromeURLRequestContextGetter::OnNewExtensions, + extension->id(), + new ChromeURLRequestContext::ExtensionInfo( + extension->path(), + extension->default_locale(), + extension->web_extent(), + extension->api_permissions()))); +} + +void PostExtensionUnloadedToContextGetter(ChromeURLRequestContextGetter* getter, + Extension* extension) { + if (!getter) + return; + ChromeThread::PostTask( + ChromeThread::IO, FROM_HERE, + NewRunnableMethod(getter, + &ChromeURLRequestContextGetter::OnUnloadedExtension, + extension->id())); +} + } // namespace // A pointer to the request context for the default profile. See comments on @@ -977,6 +1005,38 @@ URLRequestContextGetter* ProfileImpl::GetRequestContextForExtensions() { return extensions_request_context_; } +void ProfileImpl::RegisterExtensionWithRequestContexts( + Extension* extension) { + // Notify the default, extension and media contexts on the IO thread. + PostExtensionLoadedToContextGetter( + static_cast<ChromeURLRequestContextGetter*>(GetRequestContext()), + extension); + PostExtensionLoadedToContextGetter( + static_cast<ChromeURLRequestContextGetter*>( + GetRequestContextForExtensions()), + extension); + PostExtensionLoadedToContextGetter( + static_cast<ChromeURLRequestContextGetter*>( + GetRequestContextForMedia()), + extension); +} + +void ProfileImpl::UnregisterExtensionWithRequestContexts( + Extension* extension) { + // Notify the default, extension and media contexts on the IO thread. + PostExtensionUnloadedToContextGetter( + static_cast<ChromeURLRequestContextGetter*>(GetRequestContext()), + extension); + PostExtensionUnloadedToContextGetter( + static_cast<ChromeURLRequestContextGetter*>( + GetRequestContextForExtensions()), + extension); + PostExtensionUnloadedToContextGetter( + static_cast<ChromeURLRequestContextGetter*>( + GetRequestContextForMedia()), + extension); +} + net::SSLConfigService* ProfileImpl::GetSSLConfigService() { return ssl_config_service_manager_->Get(); } diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h index 91faad0..15cb97a 100644 --- a/chrome/browser/profile.h +++ b/chrome/browser/profile.h @@ -289,6 +289,18 @@ class Profile { // is only used for a separate cookie store currently. virtual URLRequestContextGetter* GetRequestContextForExtensions() = 0; + // Called by the ExtensionsService that lives in this profile. Gives the + // profile a chance to react to the load event before the EXTENSION_LOADED + // notification has fired. The purpose for handling this event first is to + // avoid race conditions by making sure URLRequestContexts learn about new + // extensions before anything else needs them to know. + virtual void RegisterExtensionWithRequestContexts(Extension* extension) {} + + // Called by the ExtensionsService that lives in this profile. Lets the + // profile clean up its RequestContexts once all the listeners to the + // EXTENSION_UNLOADED notification have finished running. + virtual void UnregisterExtensionWithRequestContexts(Extension* extension) {} + // Returns the SSLConfigService for this profile. virtual net::SSLConfigService* GetSSLConfigService() = 0; @@ -471,6 +483,8 @@ class ProfileImpl : public Profile, virtual URLRequestContextGetter* GetRequestContext(); virtual URLRequestContextGetter* GetRequestContextForMedia(); virtual URLRequestContextGetter* GetRequestContextForExtensions(); + virtual void RegisterExtensionWithRequestContexts(Extension* extension); + virtual void UnregisterExtensionWithRequestContexts(Extension* extension); virtual net::SSLConfigService* GetSSLConfigService(); virtual HostContentSettingsMap* GetHostContentSettingsMap(); virtual HostZoomMap* GetHostZoomMap(); diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 3dfcf63..cb65791 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -922,18 +922,26 @@ void ResourceMessageFilter::OnClipboardReadHTML(Clipboard::Buffer buffer, #endif void ResourceMessageFilter::OnCheckNotificationPermission( - const GURL& source_url, const std::string& application_id, int* result) { + const GURL& source_url, int* result) { + *result = WebKit::WebNotificationPresenter::PermissionNotAllowed; + ChromeURLRequestContext* context = GetRequestContextForURL(source_url); - if (!application_id.empty() && - context->CheckURLAccessToExtensionPermission( - source_url, application_id, Extension::kNotificationPermission)) { + if (context->CheckURLAccessToExtensionPermission(source_url, + Extension::kNotificationPermission)) { *result = WebKit::WebNotificationPresenter::PermissionAllowed; return; } // Fall back to the regular notification preferences, which works on an // origin basis. - *result = notification_prefs_->HasPermission(source_url.GetOrigin()); + // Note: An earlier implemention of checking the notification permission for + // extensions persisted the permission in the preferences. To avoid + // erroneously granting permission to an extension that has since been removed + // from the preferences, we only check for non-extension schemes. All + // extension cases (chrome-extension and web-content) are now handled by + // the above call to CheckURLAccessToExtensionPermission. + if (!source_url.SchemeIs(chrome::kExtensionScheme)) + *result = notification_prefs_->HasPermission(source_url.GetOrigin()); } void ResourceMessageFilter::OnGetMimeTypeFromExtension( diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h index 4c6e2e6..036ac7f 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -222,7 +222,6 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, #endif void OnCheckNotificationPermission(const GURL& source_url, - const std::string& application_id, int* permission_level); #if !defined(OS_MACOSX) diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index bf2ac2b..41c8f4d 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -1986,9 +1986,8 @@ IPC_BEGIN_MESSAGES(ViewHost) IPC_MESSAGE_ROUTED2(ViewHostMsg_RequestNotificationPermission, GURL /* origin */, int /* callback_context */) - IPC_SYNC_MESSAGE_ROUTED2_1(ViewHostMsg_CheckNotificationPermission, + IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_CheckNotificationPermission, GURL /* source page */, - std::string /* application id */, int /* permission_result */) // Sent if the worker object has sent a ViewHostMsg_CreateDedicatedWorker diff --git a/chrome/renderer/notification_provider.cc b/chrome/renderer/notification_provider.cc index 1bcefee..45fb7b9 100644 --- a/chrome/renderer/notification_provider.cc +++ b/chrome/renderer/notification_provider.cc @@ -52,12 +52,11 @@ void NotificationProvider::objectDestroyed( } WebNotificationPresenter::Permission NotificationProvider::checkPermission( - const WebURL& url, WebDocument* document) { + const WebURL& url) { int permission; Send(new ViewHostMsg_CheckNotificationPermission( view_->routing_id(), url, - document ? UTF16ToASCII(document->applicationID()) : "", &permission)); return static_cast<WebNotificationPresenter::Permission>(permission); } diff --git a/chrome/renderer/notification_provider.h b/chrome/renderer/notification_provider.h index 85cda25..1eb7dda 100644 --- a/chrome/renderer/notification_provider.h +++ b/chrome/renderer/notification_provider.h @@ -29,7 +29,7 @@ class NotificationProvider : public WebKit::WebNotificationPresenter { virtual void cancel(const WebKit::WebNotification& proxy); virtual void objectDestroyed(const WebKit::WebNotification& proxy); virtual WebKit::WebNotificationPresenter::Permission checkPermission( - const WebKit::WebURL& url, WebKit::WebDocument* document); + const WebKit::WebURL& url); virtual void requestPermission(const WebKit::WebString& origin, WebKit::WebNotificationPermissionCallback* callback); diff --git a/webkit/database/database_tracker.cc b/webkit/database/database_tracker.cc index ea1994e..38c6298 100644 --- a/webkit/database/database_tracker.cc +++ b/webkit/database/database_tracker.cc @@ -208,6 +208,11 @@ void DatabaseTracker::SetOriginQuotaInMemory(const string16& origin_identifier, in_memory_quotas_[origin_identifier] = new_quota; } +void DatabaseTracker::ResetOriginQuotaInMemory( + const string16& origin_identifier) { + in_memory_quotas_.erase(origin_identifier); +} + bool DatabaseTracker::DeleteClosedDatabase(const string16& origin_identifier, const string16& database_name) { if (!LazyInit()) diff --git a/webkit/database/database_tracker.h b/webkit/database/database_tracker.h index d1d5a43..f7468e4 100644 --- a/webkit/database/database_tracker.h +++ b/webkit/database/database_tracker.h @@ -126,6 +126,7 @@ class DatabaseTracker void SetOriginQuota(const string16& origin_identifier, int64 new_quota); void SetOriginQuotaInMemory(const string16& origin_identifier, int64 new_quota); + void ResetOriginQuotaInMemory(const string16& origin_identifier); int64 GetDefaultQuota() { return default_quota_; } // Sets the default quota for all origins. Should be used in tests only. |