Commit bc8979a1 authored by rdevlin.cronin's avatar rdevlin.cronin Committed by Commit bot

Gather metrics on hosted app unlimitedStorage usage

BUG=416691

Review URL: https://codereview.chromium.org/612983004

Cr-Commit-Position: refs/heads/master@{#297323}
parent 124caf02
...@@ -1008,7 +1008,7 @@ void ExtensionService::NotifyExtensionLoaded(const Extension* extension) { ...@@ -1008,7 +1008,7 @@ void ExtensionService::NotifyExtensionLoaded(const Extension* extension) {
// TODO(kalman): Convert ExtensionSpecialStoragePolicy to a // TODO(kalman): Convert ExtensionSpecialStoragePolicy to a
// BrowserContextKeyedService and use ExtensionRegistryObserver. // BrowserContextKeyedService and use ExtensionRegistryObserver.
profile_->GetExtensionSpecialStoragePolicy()-> profile_->GetExtensionSpecialStoragePolicy()->
GrantRightsForExtension(extension); GrantRightsForExtension(extension, profile_);
// TODO(kalman): This is broken. The crash reporter is process-wide so doesn't // TODO(kalman): This is broken. The crash reporter is process-wide so doesn't
// work properly multi-profile. Besides which, it should be using // work properly multi-profile. Besides which, it should be using
......
...@@ -7,26 +7,73 @@ ...@@ -7,26 +7,73 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/histogram.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "chrome/browser/content_settings/cookie_settings.h" #include "chrome/browser/content_settings/cookie_settings.h"
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/manifest_handlers/app_isolation_info.h" #include "chrome/common/extensions/manifest_handlers/app_isolation_info.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/url_constants.h" #include "chrome/common/url_constants.h"
#include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h" #include "components/content_settings/core/common/content_settings_types.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/url_constants.h" #include "content/public/common/url_constants.h"
#include "extensions/common/constants.h" #include "extensions/common/constants.h"
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
#include "extensions/common/extension_set.h" #include "extensions/common/extension_set.h"
#include "extensions/common/permissions/permissions_data.h" #include "extensions/common/permissions/permissions_data.h"
#include "storage/browser/quota/quota_manager.h"
#include "storage/common/quota/quota_status_code.h"
#include "storage/common/quota/quota_types.h"
using content::BrowserThread; using content::BrowserThread;
using extensions::APIPermission; using extensions::APIPermission;
using extensions::Extension; using extensions::Extension;
using storage::SpecialStoragePolicy; using storage::SpecialStoragePolicy;
namespace {
void ReportQuotaUsage(storage::QuotaStatusCode code, int64 usage, int64 quota) {
if (code == storage::kQuotaStatusOk) {
// We're interested in the amount of space hosted apps are using. Record it
// when the extension is granted the unlimited storage permission (once per
// extension load, so on average once per run).
UMA_HISTOGRAM_MEMORY_KB("Extensions.HostedAppUnlimitedStorageUsage", usage);
}
}
// Log the usage for a hosted app with unlimited storage.
void LogHostedAppUnlimitedStorageUsage(
scoped_refptr<const Extension> extension,
content::BrowserContext* browser_context) {
GURL launch_url =
extensions::AppLaunchInfo::GetLaunchWebURL(extension.get()).GetOrigin();
content::StoragePartition* partition =
browser_context ? // |browser_context| can be NULL in unittests.
content::BrowserContext::GetStoragePartitionForSite(browser_context,
launch_url) :
NULL;
if (partition) {
// We only have to query for kStorageTypePersistent data usage, because apps
// cannot ask for any more temporary storage, according to
// https://developers.google.com/chrome/whitepapers/storage.
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&storage::QuotaManager::GetUsageAndQuotaForWebApps,
partition->GetQuotaManager(),
launch_url,
storage::kStorageTypePersistent,
base::Bind(&ReportQuotaUsage)));
}
}
} // namespace
ExtensionSpecialStoragePolicy::ExtensionSpecialStoragePolicy( ExtensionSpecialStoragePolicy::ExtensionSpecialStoragePolicy(
CookieSettings* cookie_settings) CookieSettings* cookie_settings)
: cookie_settings_(cookie_settings) {} : cookie_settings_(cookie_settings) {}
...@@ -101,7 +148,8 @@ ExtensionSpecialStoragePolicy::ExtensionsProtectingOrigin( ...@@ -101,7 +148,8 @@ ExtensionSpecialStoragePolicy::ExtensionsProtectingOrigin(
} }
void ExtensionSpecialStoragePolicy::GrantRightsForExtension( void ExtensionSpecialStoragePolicy::GrantRightsForExtension(
const extensions::Extension* extension) { const extensions::Extension* extension,
content::BrowserContext* browser_context) {
DCHECK(extension); DCHECK(extension);
if (!(NeedsProtection(extension) || if (!(NeedsProtection(extension) ||
extension->permissions_data()->HasAPIPermission( extension->permissions_data()->HasAPIPermission(
...@@ -124,8 +172,12 @@ void ExtensionSpecialStoragePolicy::GrantRightsForExtension( ...@@ -124,8 +172,12 @@ void ExtensionSpecialStoragePolicy::GrantRightsForExtension(
if (extension->permissions_data()->HasAPIPermission( if (extension->permissions_data()->HasAPIPermission(
APIPermission::kUnlimitedStorage) && APIPermission::kUnlimitedStorage) &&
unlimited_extensions_.Add(extension)) unlimited_extensions_.Add(extension)) {
if (extension->is_hosted_app())
LogHostedAppUnlimitedStorageUsage(extension, browser_context);
change_flags |= SpecialStoragePolicy::STORAGE_UNLIMITED; change_flags |= SpecialStoragePolicy::STORAGE_UNLIMITED;
}
if (extension->permissions_data()->HasAPIPermission( if (extension->permissions_data()->HasAPIPermission(
APIPermission::kFileBrowserHandler)) APIPermission::kFileBrowserHandler))
......
...@@ -15,6 +15,10 @@ ...@@ -15,6 +15,10 @@
class CookieSettings; class CookieSettings;
namespace content {
class BrowserContext;
}
namespace extensions { namespace extensions {
class Extension; class Extension;
} }
...@@ -37,7 +41,8 @@ class ExtensionSpecialStoragePolicy : public storage::SpecialStoragePolicy { ...@@ -37,7 +41,8 @@ class ExtensionSpecialStoragePolicy : public storage::SpecialStoragePolicy {
virtual bool HasSessionOnlyOrigins() OVERRIDE; virtual bool HasSessionOnlyOrigins() OVERRIDE;
// Methods used by the ExtensionService to populate this class. // Methods used by the ExtensionService to populate this class.
void GrantRightsForExtension(const extensions::Extension* extension); void GrantRightsForExtension(const extensions::Extension* extension,
content::BrowserContext* browser_context);
void RevokeRightsForExtension(const extensions::Extension* extension); void RevokeRightsForExtension(const extensions::Extension* extension);
void RevokeRightsForAllExtensions(); void RevokeRightsForAllExtensions();
......
...@@ -198,7 +198,7 @@ TEST_F(ExtensionSpecialStoragePolicyTest, EmptyPolicy) { ...@@ -198,7 +198,7 @@ TEST_F(ExtensionSpecialStoragePolicyTest, EmptyPolicy) {
TEST_F(ExtensionSpecialStoragePolicyTest, AppWithProtectedStorage) { TEST_F(ExtensionSpecialStoragePolicyTest, AppWithProtectedStorage) {
scoped_refptr<Extension> extension(CreateProtectedApp()); scoped_refptr<Extension> extension(CreateProtectedApp());
policy_->GrantRightsForExtension(extension.get()); policy_->GrantRightsForExtension(extension.get(), NULL);
ExtensionSet protecting_extensions; ExtensionSet protecting_extensions;
protecting_extensions.Insert(extension); protecting_extensions.Insert(extension);
ExtensionSet empty_set; ExtensionSet empty_set;
...@@ -219,7 +219,7 @@ TEST_F(ExtensionSpecialStoragePolicyTest, AppWithProtectedStorage) { ...@@ -219,7 +219,7 @@ TEST_F(ExtensionSpecialStoragePolicyTest, AppWithProtectedStorage) {
TEST_F(ExtensionSpecialStoragePolicyTest, AppWithUnlimitedStorage) { TEST_F(ExtensionSpecialStoragePolicyTest, AppWithUnlimitedStorage) {
scoped_refptr<Extension> extension(CreateUnlimitedApp()); scoped_refptr<Extension> extension(CreateUnlimitedApp());
policy_->GrantRightsForExtension(extension.get()); policy_->GrantRightsForExtension(extension.get(), NULL);
ExtensionSet protecting_extensions; ExtensionSet protecting_extensions;
protecting_extensions.Insert(extension); protecting_extensions.Insert(extension);
ExtensionSet empty_set; ExtensionSet empty_set;
...@@ -253,9 +253,9 @@ TEST_F(ExtensionSpecialStoragePolicyTest, CanQueryDiskSize) { ...@@ -253,9 +253,9 @@ TEST_F(ExtensionSpecialStoragePolicyTest, CanQueryDiskSize) {
scoped_refptr<Extension> regular_app(CreateRegularApp()); scoped_refptr<Extension> regular_app(CreateRegularApp());
scoped_refptr<Extension> protected_app(CreateProtectedApp()); scoped_refptr<Extension> protected_app(CreateProtectedApp());
scoped_refptr<Extension> unlimited_app(CreateUnlimitedApp()); scoped_refptr<Extension> unlimited_app(CreateUnlimitedApp());
policy_->GrantRightsForExtension(regular_app.get()); policy_->GrantRightsForExtension(regular_app.get(), NULL);
policy_->GrantRightsForExtension(protected_app.get()); policy_->GrantRightsForExtension(protected_app.get(), NULL);
policy_->GrantRightsForExtension(unlimited_app.get()); policy_->GrantRightsForExtension(unlimited_app.get(), NULL);
EXPECT_FALSE(policy_->CanQueryDiskSize(kHttpUrl)); EXPECT_FALSE(policy_->CanQueryDiskSize(kHttpUrl));
EXPECT_FALSE(policy_->CanQueryDiskSize(kExtensionUrl)); EXPECT_FALSE(policy_->CanQueryDiskSize(kExtensionUrl));
...@@ -268,7 +268,7 @@ TEST_F(ExtensionSpecialStoragePolicyTest, HasIsolatedStorage) { ...@@ -268,7 +268,7 @@ TEST_F(ExtensionSpecialStoragePolicyTest, HasIsolatedStorage) {
const GURL kHttpUrl("http://foo"); const GURL kHttpUrl("http://foo");
const GURL kExtensionUrl("chrome-extension://bar"); const GURL kExtensionUrl("chrome-extension://bar");
scoped_refptr<Extension> app(CreateRegularApp()); scoped_refptr<Extension> app(CreateRegularApp());
policy_->GrantRightsForExtension(app.get()); policy_->GrantRightsForExtension(app.get(), NULL);
EXPECT_FALSE(policy_->HasIsolatedStorage(kHttpUrl)); EXPECT_FALSE(policy_->HasIsolatedStorage(kHttpUrl));
EXPECT_FALSE(policy_->HasIsolatedStorage(kExtensionUrl)); EXPECT_FALSE(policy_->HasIsolatedStorage(kExtensionUrl));
...@@ -278,8 +278,8 @@ TEST_F(ExtensionSpecialStoragePolicyTest, HasIsolatedStorage) { ...@@ -278,8 +278,8 @@ TEST_F(ExtensionSpecialStoragePolicyTest, HasIsolatedStorage) {
TEST_F(ExtensionSpecialStoragePolicyTest, OverlappingApps) { TEST_F(ExtensionSpecialStoragePolicyTest, OverlappingApps) {
scoped_refptr<Extension> protected_app(CreateProtectedApp()); scoped_refptr<Extension> protected_app(CreateProtectedApp());
scoped_refptr<Extension> unlimited_app(CreateUnlimitedApp()); scoped_refptr<Extension> unlimited_app(CreateUnlimitedApp());
policy_->GrantRightsForExtension(protected_app.get()); policy_->GrantRightsForExtension(protected_app.get(), NULL);
policy_->GrantRightsForExtension(unlimited_app.get()); policy_->GrantRightsForExtension(unlimited_app.get(), NULL);
ExtensionSet protecting_extensions; ExtensionSet protecting_extensions;
ExtensionSet empty_set; ExtensionSet empty_set;
protecting_extensions.Insert(protected_app); protecting_extensions.Insert(protected_app);
...@@ -371,14 +371,14 @@ TEST_F(ExtensionSpecialStoragePolicyTest, NotificationTest) { ...@@ -371,14 +371,14 @@ TEST_F(ExtensionSpecialStoragePolicyTest, NotificationTest) {
for (size_t i = 0; i < arraysize(apps); ++i) { for (size_t i = 0; i < arraysize(apps); ++i) {
SCOPED_TRACE(testing::Message() << "i: " << i); SCOPED_TRACE(testing::Message() << "i: " << i);
observer.ExpectGrant(apps[i]->id(), change_flags[i]); observer.ExpectGrant(apps[i]->id(), change_flags[i]);
policy_->GrantRightsForExtension(apps[i].get()); policy_->GrantRightsForExtension(apps[i].get(), NULL);
message_loop.RunUntilIdle(); message_loop.RunUntilIdle();
EXPECT_TRUE(observer.IsCompleted()); EXPECT_TRUE(observer.IsCompleted());
} }
for (size_t i = 0; i < arraysize(apps); ++i) { for (size_t i = 0; i < arraysize(apps); ++i) {
SCOPED_TRACE(testing::Message() << "i: " << i); SCOPED_TRACE(testing::Message() << "i: " << i);
policy_->GrantRightsForExtension(apps[i].get()); policy_->GrantRightsForExtension(apps[i].get(), NULL);
message_loop.RunUntilIdle(); message_loop.RunUntilIdle();
EXPECT_TRUE(observer.IsCompleted()); EXPECT_TRUE(observer.IsCompleted());
} }
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/metrics/histogram.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "extensions/browser/api/storage/settings_storage_factory.h" #include "extensions/browser/api/storage/settings_storage_factory.h"
#include "extensions/browser/api/storage/settings_storage_quota_enforcer.h" #include "extensions/browser/api/storage/settings_storage_quota_enforcer.h"
...@@ -93,15 +92,6 @@ ValueStore* LocalValueStoreCache::GetStorage( ...@@ -93,15 +92,6 @@ ValueStore* LocalValueStoreCache::GetStorage(
quota_, storage_factory_->Create(file_path, extension->id()))); quota_, storage_factory_->Create(file_path, extension->id())));
DCHECK(storage.get()); DCHECK(storage.get());
if (extension->permissions_data()->HasAPIPermission(
APIPermission::kUnlimitedStorage) &&
extension->is_hosted_app()) {
// We're interested in the amount of space hosted apps are using. Record it
// the first time we load the storage for the extension.
UMA_HISTOGRAM_MEMORY_KB("Extensions.HostedAppUnlimitedStorageUsage",
storage->GetBytesInUse());
}
storage_map_[extension->id()] = storage; storage_map_[extension->id()] = storage;
return storage.get(); return storage.get();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment