Provide a profile.GetAppCacheService() accessor and add two helper methods to ChromeAppCacheService to override the default quota for an origin.

BUG=49993
TESTS=existing tests apply

Review URL: http://codereview.chromium.org/2819091

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@55773 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/appcache/chrome_appcache_service.cc b/chrome/browser/appcache/chrome_appcache_service.cc
index 5f58b29..6188a3f 100644
--- a/chrome/browser/appcache/chrome_appcache_service.cc
+++ b/chrome/browser/appcache/chrome_appcache_service.cc
@@ -45,26 +45,27 @@
 
 // ----------------------------------------------------------------------------
 
-ChromeAppCacheService::ChromeAppCacheService(
-    const FilePath& profile_path,
-    ChromeURLRequestContext* request_context) {
+ChromeAppCacheService::ChromeAppCacheService() {
+}
+
+void ChromeAppCacheService::InitializeOnIOThread(
+    const FilePath& profile_path, bool is_incognito,
+    scoped_refptr<HostContentSettingsMap> content_settings_map) {
   DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
-  DCHECK(request_context);
 
   if (!has_initialized_thread_ids) {
     has_initialized_thread_ids = true;
     appcache::AppCacheThread::Init(ChromeThread::DB, ChromeThread::IO);
   }
 
-  host_contents_settings_map_ = request_context->host_content_settings_map();
+  host_contents_settings_map_ = content_settings_map;
   registrar_.Add(
       this, NotificationType::PURGE_MEMORY, NotificationService::AllSources());
 
   // Init our base class.
-  Initialize(request_context->is_off_the_record() ?
-                 FilePath() : profile_path.Append(chrome::kAppCacheDirname),
-             ChromeThread::GetMessageLoopProxyForThread(ChromeThread::CACHE));
-  set_request_context(request_context);
+  Initialize(
+      is_incognito ? FilePath() : profile_path.Append(chrome::kAppCacheDirname),
+      ChromeThread::GetMessageLoopProxyForThread(ChromeThread::CACHE));
   set_appcache_policy(this);
 }
 
@@ -72,6 +73,19 @@
   DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
 }
 
+void ChromeAppCacheService::SetOriginQuotaInMemory(
+    const GURL& origin, int64 quota) {
+  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+  if (storage())
+    storage()->SetOriginQuotaInMemory(origin, quota);
+}
+
+void ChromeAppCacheService::ResetOriginQuotaInMemory(const GURL& origin) {
+  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+  if (storage())
+    storage()->ResetOriginQuotaInMemory(origin);
+}
+
 // static
 void ChromeAppCacheService::ClearLocalState(const FilePath& profile_path) {
   file_util::Delete(profile_path.Append(chrome::kAppCacheDirname), true);
diff --git a/chrome/browser/appcache/chrome_appcache_service.h b/chrome/browser/appcache/chrome_appcache_service.h
index 6d5df41..957dbd0 100644
--- a/chrome/browser/appcache/chrome_appcache_service.h
+++ b/chrome/browser/appcache/chrome_appcache_service.h
@@ -22,7 +22,7 @@
 // object, and those URLRequestContexts are refcounted independently of the
 // owning profile.
 //
-// All methods, including the ctor and dtor, are expected to be called on
+// All methods, except the ctor, are expected to be called on
 // the IO thread (unless specifically called out in doc comments).
 class ChromeAppCacheService
     : public base::RefCountedThreadSafe<ChromeAppCacheService,
@@ -31,8 +31,16 @@
       public appcache::AppCachePolicy,
       public NotificationObserver {
  public:
-  ChromeAppCacheService(const FilePath& profile_path,
-                        ChromeURLRequestContext* request_context);
+  ChromeAppCacheService();
+
+  void InitializeOnIOThread(
+      const FilePath& profile_path, bool is_incognito,
+      scoped_refptr<HostContentSettingsMap> content_settings_map);
+
+  // Helpers used by the extension service to grant and revoke
+  // unlimited_storage to app extensions.
+  void SetOriginQuotaInMemory(const GURL& origin, int64 quota);
+  void ResetOriginQuotaInMemory(const GURL& origin);
 
   static void ClearLocalState(const FilePath& profile_path);
 
diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc
index a67e506..82ffd3dc 100644
--- a/chrome/browser/net/chrome_url_request_context.cc
+++ b/chrome/browser/net/chrome_url_request_context.cc
@@ -302,9 +302,7 @@
   context->set_cookie_policy(
       new ChromeCookiePolicy(host_content_settings_map_));
 
-  // Create a new AppCacheService.
-  context->set_appcache_service(
-      new ChromeAppCacheService(profile_dir_path_, context));
+  appcache_service_->set_request_context(context);
 
 #if defined(USE_NSS)
   // TODO(ukai): find a better way to set the URLRequestContext for OCSP.
@@ -410,9 +408,7 @@
   context->set_ftp_transaction_factory(
       new net::FtpNetworkLayer(context->host_resolver()));
 
-  // Create a separate AppCacheService for OTR mode.
-  context->set_appcache_service(
-      new ChromeAppCacheService(profile_dir_path_, context));
+  appcache_service_->set_request_context(context);
 
   context->set_net_log(io_thread_globals->net_log.get());
   return context;
@@ -502,9 +498,6 @@
 
   context->set_http_transaction_factory(cache);
 
-  // Use the same appcache service as the profile's main context.
-  context->set_appcache_service(main_context->appcache_service());
-
   return context;
 }
 
@@ -984,11 +977,9 @@
     user_script_dir_path_ = profile->GetUserScriptMaster()->user_script_dir();
 
   ssl_config_service_ = profile->GetSSLConfigService();
-
   profile_dir_path_ = profile->GetPath();
-
   cookie_monster_delegate_ = new ChromeCookieMonsterDelegate(profile);
-
+  appcache_service_ = profile->GetAppCacheService();
   database_tracker_ = profile->GetDatabaseTracker();
 }
 
@@ -1012,6 +1003,7 @@
   context->set_transport_security_state(
       transport_security_state_);
   context->set_ssl_config_service(ssl_config_service_);
+  context->set_appcache_service(appcache_service_);
   context->set_database_tracker(database_tracker_);
 }
 
diff --git a/chrome/browser/net/chrome_url_request_context.h b/chrome/browser/net/chrome_url_request_context.h
index 1e7065e..dff0e6f 100644
--- a/chrome/browser/net/chrome_url_request_context.h
+++ b/chrome/browser/net/chrome_url_request_context.h
@@ -393,6 +393,7 @@
   // user scripts.
   FilePath user_script_dir_path_;
   scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
+  scoped_refptr<ChromeAppCacheService> appcache_service_;
   scoped_refptr<webkit_database::DatabaseTracker> database_tracker_;
   scoped_refptr<HostZoomMap> host_zoom_map_;
   scoped_refptr<net::TransportSecurityState> transport_security_state_;
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index 7b3f7d27..26392e88 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -168,6 +168,19 @@
     return profile_;
   }
 
+  virtual ChromeAppCacheService* GetAppCacheService() {
+    if (!appcache_service_) {
+      appcache_service_ = new ChromeAppCacheService;
+      ChromeThread::PostTask(
+          ChromeThread::IO, FROM_HERE,
+          NewRunnableMethod(appcache_service_.get(),
+                            &ChromeAppCacheService::InitializeOnIOThread,
+                            GetPath(), IsOffTheRecord(),
+                            make_scoped_refptr(GetHostContentSettingsMap())));
+    }
+    return appcache_service_;
+  }
+
   virtual webkit_database::DatabaseTracker* GetDatabaseTracker() {
     if (!db_tracker_) {
       db_tracker_ = new webkit_database::DatabaseTracker(
@@ -531,6 +544,8 @@
   // Time we were started.
   Time start_time_;
 
+  scoped_refptr<ChromeAppCacheService> appcache_service_;
+
   // The main database tracker for this profile.
   // Should be used only on the file thread.
   scoped_refptr<webkit_database::DatabaseTracker> db_tracker_;
diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h
index 2bf2c22..6403c8f 100644
--- a/chrome/browser/profile.h
+++ b/chrome/browser/profile.h
@@ -37,6 +37,7 @@
 class BackgroundContentsService;
 class BookmarkModel;
 class BrowserThemeProvider;
+class ChromeAppCacheService;
 class ChromeURLRequestContextGetter;
 class DesktopNotificationService;
 class DownloadManager;
@@ -154,6 +155,9 @@
   // profile is not off the record.
   virtual Profile* GetOriginalProfile() = 0;
 
+  // Returns a pointer to the ChromeAppCacheService instance for this profile.
+  virtual ChromeAppCacheService* GetAppCacheService() = 0;
+
   // Returns a pointer to the DatabaseTracker instance for this profile.
   virtual webkit_database::DatabaseTracker* GetDatabaseTracker() = 0;
 
diff --git a/chrome/browser/profile_impl.cc b/chrome/browser/profile_impl.cc
index 9cfc4a2..18b3a02e 100644
--- a/chrome/browser/profile_impl.cc
+++ b/chrome/browser/profile_impl.cc
@@ -535,6 +535,19 @@
   return this;
 }
 
+ChromeAppCacheService* ProfileImpl::GetAppCacheService() {
+  if (!appcache_service_) {
+    appcache_service_ = new ChromeAppCacheService;
+    ChromeThread::PostTask(
+        ChromeThread::IO, FROM_HERE,
+        NewRunnableMethod(appcache_service_.get(),
+                          &ChromeAppCacheService::InitializeOnIOThread,
+                          GetPath(), IsOffTheRecord(),
+                          make_scoped_refptr(GetHostContentSettingsMap())));
+  }
+  return appcache_service_;
+}
+
 webkit_database::DatabaseTracker* ProfileImpl::GetDatabaseTracker() {
   if (!db_tracker_) {
     db_tracker_ = new webkit_database::DatabaseTracker(
diff --git a/chrome/browser/profile_impl.h b/chrome/browser/profile_impl.h
index b61a7f7e..4e8195a 100644
--- a/chrome/browser/profile_impl.h
+++ b/chrome/browser/profile_impl.h
@@ -33,6 +33,7 @@
   virtual void DestroyOffTheRecordProfile();
   virtual bool HasOffTheRecordProfile();
   virtual Profile* GetOriginalProfile();
+  virtual ChromeAppCacheService* GetAppCacheService();
   virtual webkit_database::DatabaseTracker* GetDatabaseTracker();
   virtual history::TopSites* GetTopSites();
   virtual VisitedLinkMaster* GetVisitedLinkMaster();
@@ -212,6 +213,10 @@
   // GetSessionService won't recreate the SessionService.
   bool shutdown_session_service_;
 
+  // The AppCacheService for this profile, shared by all requests contexts
+  // associated with this profile. Should only be used on the IO thread.
+  scoped_refptr<ChromeAppCacheService> appcache_service_;
+
   // The main database tracker for this profile.
   // Should be used only on the file thread.
   scoped_refptr<webkit_database::DatabaseTracker> db_tracker_;