summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/extensions_service.cc50
-rw-r--r--chrome/browser/net/chrome_url_request_context.cc40
-rw-r--r--chrome/browser/net/chrome_url_request_context.h8
-rw-r--r--chrome/browser/notifications/desktop_notification_service.cc31
-rw-r--r--chrome/browser/notifications/desktop_notification_service.h10
-rw-r--r--chrome/browser/profile.cc60
-rw-r--r--chrome/browser/profile.h14
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc18
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h1
-rw-r--r--chrome/common/render_messages_internal.h3
-rw-r--r--chrome/renderer/notification_provider.cc3
-rw-r--r--chrome/renderer/notification_provider.h2
-rw-r--r--webkit/database/database_tracker.cc5
-rw-r--r--webkit/database/database_tracker.h1
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.