| Index: chrome/browser/profiles/profile_impl_io_data.cc | 
| diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc | 
| index 3fe1945ac41b1de0cc00afd1082e5ce5fd777ed0..307fb0922c8af263498a978f0cbc07c734c61566 100644 | 
| --- a/chrome/browser/profiles/profile_impl_io_data.cc | 
| +++ b/chrome/browser/profiles/profile_impl_io_data.cc | 
| @@ -17,6 +17,7 @@ | 
| #include "chrome/browser/net/sqlite_persistent_cookie_store.h" | 
| #include "chrome/common/chrome_constants.h" | 
| #include "chrome/common/chrome_switches.h" | 
| +#include "chrome/common/extensions/extension.h" | 
| #include "chrome/common/url_constants.h" | 
| #include "net/ftp/ftp_network_layer.h" | 
| #include "net/http/http_cache.h" | 
| @@ -37,6 +38,14 @@ ProfileImplIOData::Handle::~Handle() { | 
| media_request_context_getter_->CleanupOnUIThread(); | 
| if (extensions_request_context_getter_) | 
| extensions_request_context_getter_->CleanupOnUIThread(); | 
| + | 
| +  // Clean up all isolated app request contexts. | 
| +  for (ChromeURLRequestContextGetterMap::iterator iter = | 
| +           app_request_context_getter_map_.begin(); | 
| +       iter != app_request_context_getter_map_.end(); | 
| +       ++iter) { | 
| +    iter->second->CleanupOnUIThread(); | 
| +  } | 
| } | 
|  | 
| void ProfileImplIOData::Handle::Init(const FilePath& cookie_path, | 
| @@ -61,6 +70,31 @@ void ProfileImplIOData::Handle::Init(const FilePath& cookie_path, | 
| io_data_->lazy_params_.reset(lazy_params); | 
| } | 
|  | 
| +void ProfileImplIOData::Handle::InitIsolatedApp(const Extension* installed_app, | 
| +                                                const FilePath& cookie_path, | 
| +                                                const FilePath& cache_path, | 
| +                                                int cache_max_size) { | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| + | 
| +  // This may be called multiple times before InitializeAppRequestContext. | 
| +  // Only do the initialization once. | 
| +  std::string id = installed_app->id(); | 
| +  if (io_data_->lazy_params_map_.find(id) != io_data_->lazy_params_map_.end()) | 
| +    return; | 
| + | 
| +  LazyParams* lazy_params = new LazyParams; | 
| +  lazy_params->cookie_path = cookie_path; | 
| +  lazy_params->cache_path = cache_path; | 
| +  lazy_params->cache_max_size = cache_max_size; | 
| + | 
| +  lazy_params->io_thread = g_browser_process->io_thread(); | 
| + | 
| +  InitializeProfileParams(profile_, &lazy_params->profile_params); | 
| + | 
| +  // Keep track of this app's LazyParams until InitializeAppRequestContext. | 
| +  io_data_->lazy_params_map_[id] = lazy_params; | 
| +} | 
| + | 
| scoped_refptr<ChromeURLRequestContextGetter> | 
| ProfileImplIOData::Handle::GetMainRequestContextGetter() const { | 
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| @@ -97,6 +131,28 @@ ProfileImplIOData::Handle::GetExtensionsRequestContextGetter() const { | 
| return extensions_request_context_getter_; | 
| } | 
|  | 
| +scoped_refptr<ChromeURLRequestContextGetter> | 
| +ProfileImplIOData::Handle::GetIsolatedAppRequestContextGetter( | 
| +    const Extension* installed_app) const { | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| +  CHECK(installed_app); | 
| +  LazyInitialize(); | 
| + | 
| +  // Keep a map of request context getters, one per requested app ID. | 
| +  std::string id = installed_app->id(); | 
| +  ChromeURLRequestContextGetterMap::iterator iter = | 
| +      app_request_context_getter_map_.find(id); | 
| +  if (iter != app_request_context_getter_map_.end()) | 
| +    return iter->second; | 
| + | 
| +  ChromeURLRequestContextGetter* context = | 
| +      ChromeURLRequestContextGetter::CreateOriginalForIsolatedApp( | 
| +          profile_, io_data_, installed_app); | 
| +  app_request_context_getter_map_[id] = context; | 
| + | 
| +  return context; | 
| +} | 
| + | 
| void ProfileImplIOData::Handle::LazyInitialize() const { | 
| if (!initialized_) { | 
| InitializeProfileParams(profile_, &io_data_->lazy_params_->profile_params); | 
| @@ -255,6 +311,98 @@ void ProfileImplIOData::LazyInitializeInternal() const { | 
| lazy_params_.reset(); | 
| } | 
|  | 
| +scoped_refptr<ProfileIOData::RequestContext> | 
| +ProfileImplIOData::InitializeAppRequestContext(const Extension* app) const { | 
| +  scoped_refptr<ProfileIOData::RequestContext> context = new RequestContext; | 
| + | 
| +  // Get the app-specific LazyParams, which was created in InitIsolatedApp. | 
| +  std::string id = app->id(); | 
| +  LazyParamsMap::iterator iter = lazy_params_map_.find(id); | 
| +  DCHECK(iter != lazy_params_map_.end()); | 
| +  scoped_ptr<LazyParams> lazy_params(iter->second); | 
| + | 
| +  IOThread* const io_thread = lazy_params->io_thread; | 
| +  IOThread::Globals* const io_thread_globals = io_thread->globals(); | 
| +  const ProfileParams& profile_params = lazy_params->profile_params; | 
| +  const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | 
| +  bool record_mode = chrome::kRecordModeEnabled && | 
| +                     command_line.HasSwitch(switches::kRecordMode); | 
| +  bool playback_mode = command_line.HasSwitch(switches::kPlaybackMode); | 
| + | 
| +  // Initialize context members. | 
| + | 
| +  ApplyProfileParamsToContext(profile_params, context); | 
| + | 
| +  scoped_refptr<ChromeCookiePolicy> cookie_policy = | 
| +      new ChromeCookiePolicy(profile_params.host_content_settings_map); | 
| +  context->set_chrome_cookie_policy(cookie_policy); | 
| + | 
| +  context->set_net_log(lazy_params->io_thread->net_log()); | 
| + | 
| +  DCHECK(network_delegate_.get()); | 
| +  context->set_network_delegate(network_delegate_.get()); | 
| + | 
| +  context->set_host_resolver(io_thread_globals->host_resolver.get()); | 
| +  context->set_cert_verifier(io_thread_globals->cert_verifier.get()); | 
| +  context->set_dnsrr_resolver(io_thread_globals->dnsrr_resolver.get()); | 
| +  context->set_http_auth_handler_factory( | 
| +      io_thread_globals->http_auth_handler_factory.get()); | 
| + | 
| +  DCHECK(dns_cert_checker_.get()); | 
| +  context->set_dns_cert_checker(dns_cert_checker_.get()); | 
| + | 
| +  net::ProxyService* proxy_service = | 
| +      CreateProxyService( | 
| +          io_thread->net_log(), | 
| +          io_thread_globals->proxy_script_fetcher_context.get(), | 
| +          lazy_params->profile_params.proxy_config_service.release(), | 
| +          command_line); | 
| +  context->set_proxy_service(proxy_service); | 
| + | 
| +  // Use a separate HTTP disk cache for isolated apps. | 
| +  net::HttpCache::DefaultBackend* app_backend = | 
| +      new net::HttpCache::DefaultBackend( | 
| +          net::DISK_CACHE, | 
| +          lazy_params->cache_path, | 
| +          lazy_params->cache_max_size, | 
| +          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE)); | 
| +  net::HttpNetworkSession* main_network_session = main_http_factory_->GetSession(); | 
| +  net::HttpCache* app_cache = | 
| +      new net::HttpCache(main_network_session, app_backend); | 
| + | 
| +  scoped_refptr<net::CookieStore> cookie_store = NULL; | 
| +  if (record_mode || playback_mode) { | 
| +    // Don't use existing cookies and use an in-memory store. | 
| +    cookie_store = new net::CookieMonster( | 
| +        NULL, profile_params.cookie_monster_delegate); | 
| +    app_cache->set_mode( | 
| +        record_mode ? net::HttpCache::RECORD : net::HttpCache::PLAYBACK); | 
| +  } | 
| + | 
| +  // Use an app-specific cookie store. | 
| +  if (!cookie_store) { | 
| +    DCHECK(!lazy_params->cookie_path.empty()); | 
| + | 
| +    scoped_refptr<SQLitePersistentCookieStore> cookie_db = | 
| +        new SQLitePersistentCookieStore(lazy_params->cookie_path); | 
| +    cookie_db->SetClearLocalStateOnExit( | 
| +        profile_params.clear_local_state_on_exit); | 
| +    cookie_store = | 
| +        new net::CookieMonster(cookie_db.get(), | 
| +                               profile_params.cookie_monster_delegate); | 
| +  } | 
| + | 
| +  context->set_cookie_store(cookie_store); | 
| + | 
| +  context->set_http_transaction_factory(app_cache); | 
| + | 
| +  context->set_ftp_transaction_factory( | 
| +      new net::FtpNetworkLayer(io_thread_globals->host_resolver.get())); | 
| + | 
| +  lazy_params_map_.erase(iter); | 
| +  return context; | 
| +} | 
| + | 
| scoped_refptr<ChromeURLRequestContext> | 
| ProfileImplIOData::AcquireMainRequestContext() const { | 
| DCHECK(main_request_context_); | 
| @@ -281,3 +429,14 @@ ProfileImplIOData::AcquireExtensionsRequestContext() const { | 
| extensions_request_context_ = NULL; | 
| return context; | 
| } | 
| + | 
| +scoped_refptr<ChromeURLRequestContext> | 
| +ProfileImplIOData::AcquireIsolatedAppRequestContext( | 
| +    const Extension* installed_app) const { | 
| +  // We create per-app contexts on demand, unlike the others above. | 
| +  scoped_refptr<RequestContext> app_request_context = | 
| +      InitializeAppRequestContext(installed_app); | 
| +  DCHECK(app_request_context); | 
| +  app_request_context->set_profile_io_data(this); | 
| +  return app_request_context; | 
| +} | 
|  |