1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file. 4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/browser/service_worker/service_worker_context_core.h" 6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/files/file_path.h" 803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/single_thread_task_runner.h" 9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/strings/string_util.h" 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/browser/service_worker/embedded_worker_registry.h" 116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "content/browser/service_worker/service_worker_cache_storage_manager.h" 120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/browser/service_worker/service_worker_context_observer.h" 135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/browser/service_worker/service_worker_context_wrapper.h" 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/service_worker/service_worker_info.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/service_worker/service_worker_job_coordinator.h" 165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/browser/service_worker/service_worker_process_manager.h" 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/browser/service_worker/service_worker_provider_host.h" 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/browser/service_worker/service_worker_register_job.h" 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/browser/service_worker/service_worker_registration.h" 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/browser/service_worker/service_worker_storage.h" 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "url/gurl.h" 23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace content { 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const base::FilePath::CharType 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ServiceWorkerContextCore::kServiceWorkerDirectory[] = 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FILE_PATH_LITERAL("Service Worker"); 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 300529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerContextCore::ProviderHostIterator::~ProviderHostIterator() {} 310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 320529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerProviderHost* 330529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerContextCore::ProviderHostIterator::GetProviderHost() { 340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!IsAtEnd()); 350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return provider_host_iterator_->GetCurrentValue(); 360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ServiceWorkerContextCore::ProviderHostIterator::Advance() { 390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!IsAtEnd()); 400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!provider_host_iterator_->IsAtEnd()); 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!process_iterator_->IsAtEnd()); 420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Advance the inner iterator. If an element is reached, we're done. 440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch provider_host_iterator_->Advance(); 450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!provider_host_iterator_->IsAtEnd()) 460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Advance the outer iterator until an element is reached, or end is hit. 490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch while (true) { 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch process_iterator_->Advance(); 51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (process_iterator_->IsAtEnd()) 520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ProviderMap* provider_map = process_iterator_->GetCurrentValue(); 540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch provider_host_iterator_.reset(new ProviderMap::iterator(provider_map)); 550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!provider_host_iterator_->IsAtEnd()) 560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool ServiceWorkerContextCore::ProviderHostIterator::IsAtEnd() { 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return process_iterator_->IsAtEnd() && 620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (!provider_host_iterator_ || provider_host_iterator_->IsAtEnd()); 630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 650529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerContextCore::ProviderHostIterator::ProviderHostIterator( 660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ProcessToProviderMap* map) 670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : map_(map) { 680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(map); 690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Initialize(); 700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ServiceWorkerContextCore::ProviderHostIterator::Initialize() { 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch process_iterator_.reset(new ProcessToProviderMap::iterator(map_)); 740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Advance to the first element. 75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch while (!process_iterator_->IsAtEnd()) { 76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ProviderMap* provider_map = process_iterator_->GetCurrentValue(); 770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch provider_host_iterator_.reset(new ProviderMap::iterator(provider_map)); 780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!provider_host_iterator_->IsAtEnd()) 790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch process_iterator_->Advance(); 810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ServiceWorkerContextCore::ServiceWorkerContextCore( 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::FilePath& path, 8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner, 8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const scoped_refptr<base::SequencedTaskRunner>& database_task_runner, 8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread, 8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) storage::QuotaManagerProxy* quota_manager_proxy, 905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ObserverListThreadSafe<ServiceWorkerContextObserver>* observer_list, 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ServiceWorkerContextWrapper* wrapper) 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : weak_factory_(this), 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) wrapper_(wrapper), 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch providers_(new ProcessToProviderMap), 956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) storage_(ServiceWorkerStorage::Create(path, 966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) AsWeakPtr(), 976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) database_task_runner, 986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) disk_cache_thread, 996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) quota_manager_proxy)), 1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) cache_manager_( 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ServiceWorkerCacheStorageManager::Create(path, 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cache_task_runner.get())), 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch embedded_worker_registry_(EmbeddedWorkerRegistry::Create(AsWeakPtr())), 1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch job_coordinator_(new ServiceWorkerJobCoordinator(AsWeakPtr())), 1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch next_handle_id_(0), 1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) next_registration_handle_id_(0), 1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu observer_list_(observer_list) { 1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 110116680a4aac90f2aa7413d9095a592090648e557Ben MurdochServiceWorkerContextCore::ServiceWorkerContextCore( 111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ServiceWorkerContextCore* old_context, 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ServiceWorkerContextWrapper* wrapper) 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : weak_factory_(this), 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch wrapper_(wrapper), 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch providers_(old_context->providers_.release()), 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) storage_( 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ServiceWorkerStorage::Create(AsWeakPtr(), old_context->storage())), 1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) cache_manager_(ServiceWorkerCacheStorageManager::Create( 1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) old_context->cache_manager())), 120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch embedded_worker_registry_(EmbeddedWorkerRegistry::Create( 121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AsWeakPtr(), 122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch old_context->embedded_worker_registry())), 123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch job_coordinator_(new ServiceWorkerJobCoordinator(AsWeakPtr())), 124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch next_handle_id_(0), 1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) next_registration_handle_id_(0), 126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch observer_list_(old_context->observer_list_) { 127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 129c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochServiceWorkerContextCore::~ServiceWorkerContextCore() { 1300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (VersionMap::iterator it = live_versions_.begin(); 1310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it != live_versions_.end(); 1320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++it) { 1330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it->second->RemoveListener(this); 1340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) weak_factory_.InvalidateWeakPtrs(); 136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost( 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int process_id, int provider_id) { 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ProviderMap* map = GetProviderMapForProcess(process_id); 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!map) 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return NULL; 143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return map->Lookup(provider_id); 144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ServiceWorkerContextCore::AddProviderHost( 147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<ServiceWorkerProviderHost> host) { 148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ServiceWorkerProviderHost* host_ptr = host.release(); // we take ownership 149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ProviderMap* map = GetProviderMapForProcess(host_ptr->process_id()); 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!map) { 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) map = new ProviderMap; 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch providers_->AddWithID(map, host_ptr->process_id()); 153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) map->AddWithID(host_ptr, host_ptr->provider_id()); 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ServiceWorkerContextCore::RemoveProviderHost( 158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int process_id, int provider_id) { 159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ProviderMap* map = GetProviderMapForProcess(process_id); 160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(map); 161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) map->Remove(provider_id); 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ServiceWorkerContextCore::RemoveAllProviderHostsForProcess( 165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int process_id) { 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (providers_->Lookup(process_id)) 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch providers_->Remove(process_id); 168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochscoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> 1710529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerContextCore::GetProviderHostIterator() { 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return make_scoped_ptr(new ProviderHostIterator(providers_.get())); 1730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ServiceWorkerContextCore::RegisterServiceWorker( 176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const GURL& pattern, 177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const GURL& script_url, 178a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ServiceWorkerProviderHost* provider_host, 179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const RegistrationCallback& callback) { 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (storage()->IsDisabled()) { 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch callback.Run(SERVICE_WORKER_ERROR_ABORT, 183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch kInvalidServiceWorkerRegistrationId, 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch kInvalidServiceWorkerVersionId); 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) job_coordinator_->Register( 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pattern, 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) script_url, 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci provider_host, 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&ServiceWorkerContextCore::RegistrationComplete, 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AsWeakPtr(), 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pattern, 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ServiceWorkerContextCore::UnregisterServiceWorker( 199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const GURL& pattern, 200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const UnregistrationCallback& callback) { 201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (storage()->IsDisabled()) { 203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch callback.Run(SERVICE_WORKER_ERROR_ABORT); 204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) job_coordinator_->Unregister( 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pattern, 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&ServiceWorkerContextCore::UnregistrationComplete, 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AsWeakPtr(), 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pattern, 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback)); 213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ServiceWorkerContextCore::UpdateServiceWorker( 2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ServiceWorkerRegistration* registration) { 2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (storage()->IsDisabled()) 2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) job_coordinator_->Update(registration); 2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ServiceWorkerContextCore::RegistrationComplete( 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const GURL& pattern, 225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const ServiceWorkerContextCore::RegistrationCallback& callback, 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ServiceWorkerStatusCode status, 227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ServiceWorkerRegistration* registration, 228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ServiceWorkerVersion* version) { 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status != SERVICE_WORKER_OK) { 230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(!version); 231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch callback.Run(status, 232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kInvalidServiceWorkerRegistrationId, 233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kInvalidServiceWorkerVersionId); 234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(version); 238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK_EQ(version->registration_id(), registration->id()); 239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch callback.Run(status, 240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch registration->id(), 241c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch version->version_id()); 2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (observer_list_.get()) { 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) observer_list_->Notify(&ServiceWorkerContextObserver::OnRegistrationStored, 244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pattern); 245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerContextCore::UnregistrationComplete( 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const GURL& pattern, 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const ServiceWorkerContextCore::UnregistrationCallback& callback, 251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ServiceWorkerStatusCode status) { 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback.Run(status); 2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (observer_list_.get()) { 254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) observer_list_->Notify(&ServiceWorkerContextObserver::OnRegistrationDeleted, 255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pattern); 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 259c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochServiceWorkerRegistration* ServiceWorkerContextCore::GetLiveRegistration( 260c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int64 id) { 261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch RegistrationsMap::iterator it = live_registrations_.find(id); 262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return (it != live_registrations_.end()) ? it->second : NULL; 263c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 264c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 265c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ServiceWorkerContextCore::AddLiveRegistration( 266c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ServiceWorkerRegistration* registration) { 267c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(!GetLiveRegistration(registration->id())); 268c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch live_registrations_[registration->id()] = registration; 269c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 270c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 271c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ServiceWorkerContextCore::RemoveLiveRegistration(int64 id) { 272c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch live_registrations_.erase(id); 273c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 274c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 275c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochServiceWorkerVersion* ServiceWorkerContextCore::GetLiveVersion( 276c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int64 id) { 277c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VersionMap::iterator it = live_versions_.find(id); 278c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return (it != live_versions_.end()) ? it->second : NULL; 279c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 280c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 281c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ServiceWorkerContextCore::AddLiveVersion(ServiceWorkerVersion* version) { 282c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(!GetLiveVersion(version->version_id())); 283c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch live_versions_[version->version_id()] = version; 2840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version->AddListener(this); 285c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 286c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 287c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ServiceWorkerContextCore::RemoveLiveVersion(int64 id) { 288c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch live_versions_.erase(id); 289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 290a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::vector<ServiceWorkerRegistrationInfo> 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ServiceWorkerContextCore::GetAllLiveRegistrationInfo() { 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<ServiceWorkerRegistrationInfo> infos; 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (std::map<int64, ServiceWorkerRegistration*>::const_iterator iter = 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) live_registrations_.begin(); 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) iter != live_registrations_.end(); 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ++iter) { 298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) infos.push_back(iter->second->GetInfo()); 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return infos; 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::vector<ServiceWorkerVersionInfo> 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ServiceWorkerContextCore::GetAllLiveVersionInfo() { 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<ServiceWorkerVersionInfo> infos; 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (std::map<int64, ServiceWorkerVersion*>::const_iterator iter = 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) live_versions_.begin(); 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) iter != live_versions_.end(); 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ++iter) { 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) infos.push_back(iter->second->GetInfo()); 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return infos; 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 315a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochint ServiceWorkerContextCore::GetNewServiceWorkerHandleId() { 316a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return next_handle_id_++; 317a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 318a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 3196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)int ServiceWorkerContextCore::GetNewRegistrationHandleId() { 3206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return next_registration_handle_id_++; 3216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 3226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 323116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ServiceWorkerContextCore::ScheduleDeleteAndStartOver() const { 324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch storage_->Disable(); 325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::MessageLoop::current()->PostTask( 326116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FROM_HERE, 327116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&ServiceWorkerContextWrapper::DeleteAndStartOver, wrapper_)); 328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 330116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ServiceWorkerContextCore::DeleteAndStartOver( 331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const StatusCallback& callback) { 332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch job_coordinator_->AbortAll(); 333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch storage_->DeleteAndStartOver(callback); 334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 3366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ServiceWorkerContextCore::SetBlobParametersForCache( 3376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) net::URLRequestContext* request_context, 33803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::WeakPtr<storage::BlobStorageContext> blob_storage_context) { 3396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 3406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) cache_manager_->SetBlobParametersForCache(request_context, 3426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) blob_storage_context); 3436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 3446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ServiceWorkerContextCore::OnWorkerStarted(ServiceWorkerVersion* version) { 3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!observer_list_.get()) 3470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 3480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStarted, 3490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version->version_id(), 3500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version->embedded_worker()->process_id(), 3510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version->embedded_worker()->thread_id()); 3520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 3530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ServiceWorkerContextCore::OnWorkerStopped(ServiceWorkerVersion* version) { 3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!observer_list_.get()) 3560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 3570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStopped, 3580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version->version_id(), 3590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version->embedded_worker()->process_id(), 3600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version->embedded_worker()->thread_id()); 3610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 3620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ServiceWorkerContextCore::OnVersionStateChanged( 3640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ServiceWorkerVersion* version) { 3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!observer_list_.get()) 3660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 3670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch observer_list_->Notify(&ServiceWorkerContextObserver::OnVersionStateChanged, 3680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version->version_id()); 3690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 3700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ServiceWorkerContextCore::OnErrorReported( 3720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ServiceWorkerVersion* version, 3730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const base::string16& error_message, 3740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int line_number, 3750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int column_number, 3760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const GURL& source_url) { 3771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!observer_list_.get()) 3780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 3790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch observer_list_->Notify( 3800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &ServiceWorkerContextObserver::OnErrorReported, 3810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version->version_id(), 3820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version->embedded_worker()->process_id(), 3830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version->embedded_worker()->thread_id(), 3840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ServiceWorkerContextObserver::ErrorInfo( 3850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch error_message, line_number, column_number, source_url)); 3860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 3870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ServiceWorkerContextCore::OnReportConsoleMessage( 3890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ServiceWorkerVersion* version, 3900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int source_identifier, 3910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int message_level, 3920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const base::string16& message, 3930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int line_number, 3940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const GURL& source_url) { 3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!observer_list_.get()) 3960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 3970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch observer_list_->Notify( 3980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &ServiceWorkerContextObserver::OnReportConsoleMessage, 3990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version->version_id(), 4000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version->embedded_worker()->process_id(), 4010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version->embedded_worker()->thread_id(), 4020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ServiceWorkerContextObserver::ConsoleMessage( 4030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch source_identifier, message_level, message, line_number, source_url)); 4040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 4050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ServiceWorkerProcessManager* ServiceWorkerContextCore::process_manager() { 4071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (wrapper_) 4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return wrapper_->process_manager(); 4091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return NULL; 410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 412f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace content 413