service_worker_storage.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/browser/service_worker/service_worker_storage.h" 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <string> 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/message_loop/message_loop.h" 90529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/browser/service_worker/service_worker_context_core.h" 10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/service_worker/service_worker_info.h" 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/browser/service_worker/service_worker_registration.h" 12a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "content/browser/service_worker/service_worker_utils.h" 130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/browser/service_worker/service_worker_version.h" 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "webkit/browser/quota/quota_manager_proxy.h" 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace content { 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace { 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid RunSoon(const tracked_objects::Location& from_here, 225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const base::Closure& closure) { 235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::MessageLoop::current()->PostTask(from_here, closure); 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid CompleteFindNow( 270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const scoped_refptr<ServiceWorkerRegistration>& registration, 280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ServiceWorkerStatusCode status, 290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const ServiceWorkerStorage::FindRegistrationCallback& callback) { 300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch callback.Run(status, registration); 310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid CompleteFindSoon( 345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const tracked_objects::Location& from_here, 350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const scoped_refptr<ServiceWorkerRegistration>& registration, 360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ServiceWorkerStatusCode status, 370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const ServiceWorkerStorage::FindRegistrationCallback& callback) { 385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu RunSoon(from_here, base::Bind(callback, status, registration)); 390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const base::FilePath::CharType kServiceWorkerDirectory[] = 42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) FILE_PATH_LITERAL("ServiceWorker"); 43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)ServiceWorkerStorage::ServiceWorkerStorage( 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::FilePath& path, 480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::WeakPtr<ServiceWorkerContextCore> context, 49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) quota::QuotaManagerProxy* quota_manager_proxy) 500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : last_registration_id_(0), 510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch last_version_id_(0), 520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch last_resource_id_(0), 530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch simulated_lazy_initted_(false), 540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch context_(context), 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) quota_manager_proxy_(quota_manager_proxy) { 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!path.empty()) 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) path_ = path.Append(kServiceWorkerDirectory); 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)ServiceWorkerStorage::~ServiceWorkerStorage() { 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ServiceWorkerStorage::FindRegistrationForPattern( 640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const GURL& scope, 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const FindRegistrationCallback& callback) { 660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch simulated_lazy_initted_ = true; 670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_refptr<ServiceWorkerRegistration> null_registration; 680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!context_) { 695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CompleteFindSoon( 705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu FROM_HERE, null_registration, SERVICE_WORKER_ERROR_FAILED, callback); 710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_refptr<ServiceWorkerRegistration> installing_registration = 750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FindInstallingRegistrationForPattern(scope); 760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (installing_registration) { 775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CompleteFindSoon( 785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu FROM_HERE, installing_registration, SERVICE_WORKER_OK, callback); 790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // See if there are any registrations for the origin. 830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch OriginRegistrationsMap::const_iterator 840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch found = stored_registrations_.find(scope.GetOrigin()); 850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (found == stored_registrations_.end()) { 865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CompleteFindSoon( 875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu FROM_HERE, null_registration, SERVICE_WORKER_ERROR_NOT_FOUND, callback); 880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Find one with a matching scope. 920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (RegistrationsMap::const_iterator it = found->second.begin(); 930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it != found->second.end(); ++it) { 940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (scope == it->second.scope) { 950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const ServiceWorkerDatabase::RegistrationData* data = &(it->second); 960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_refptr<ServiceWorkerRegistration> registration = 970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch context_->GetLiveRegistration(data->registration_id); 980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (registration) { 995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CompleteFindSoon(FROM_HERE, registration, SERVICE_WORKER_OK, callback); 1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch registration = CreateRegistration(data); 1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CompleteFindSoon(FROM_HERE, registration, SERVICE_WORKER_OK, callback); 1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CompleteFindSoon( 1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu FROM_HERE, null_registration, SERVICE_WORKER_ERROR_NOT_FOUND, callback); 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ServiceWorkerStorage::FindRegistrationForDocument( 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const GURL& document_url, 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const FindRegistrationCallback& callback) { 1160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch simulated_lazy_initted_ = true; 1170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_refptr<ServiceWorkerRegistration> null_registration; 1180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!context_) { 1190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CompleteFindNow(null_registration, SERVICE_WORKER_ERROR_FAILED, callback); 1200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // See if there are any registrations for the origin. 1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch OriginRegistrationsMap::const_iterator 1250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch found = stored_registrations_.find(document_url.GetOrigin()); 1260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (found == stored_registrations_.end()) { 1270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Look for something currently being installed. 1280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_refptr<ServiceWorkerRegistration> installing_registration = 1290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FindInstallingRegistrationForDocument(document_url); 1300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (installing_registration) { 1310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CompleteFindNow(installing_registration, SERVICE_WORKER_OK, callback); 1320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Return syncly to simulate this class having an in memory map of 1360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // origins with registrations. 1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CompleteFindNow(null_registration, SERVICE_WORKER_ERROR_NOT_FOUND, 1380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch callback); 1390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Find one with a pattern match. 1430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (RegistrationsMap::const_iterator it = found->second.begin(); 1440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it != found->second.end(); ++it) { 1450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // TODO(michaeln): if there are multiple matches the one with 1460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // the longest scope should win. 1470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (ServiceWorkerUtils::ScopeMatches(it->second.scope, document_url)) { 1480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const ServiceWorkerDatabase::RegistrationData* data = &(it->second); 1490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // If its in the live map, return syncly to simulate this class having 1510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // iterated over the values in that map instead of reading the db. 1520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_refptr<ServiceWorkerRegistration> registration = 1530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch context_->GetLiveRegistration(data->registration_id); 1540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (registration) { 1550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CompleteFindNow(registration, SERVICE_WORKER_OK, callback); 1560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // If we have to create a new instance, return it asyncly to simulate 1600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // having had to retreive the RegistrationData from the db. 1610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch registration = CreateRegistration(data); 1625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CompleteFindSoon(FROM_HERE, registration, SERVICE_WORKER_OK, callback); 1630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Look for something currently being installed. 1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // TODO(michaeln): Should be mixed in with the stored registrations 1690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // for this test. 1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_refptr<ServiceWorkerRegistration> installing_registration = 1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FindInstallingRegistrationForDocument(document_url); 1720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (installing_registration) { 1735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CompleteFindSoon( 1745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu FROM_HERE, installing_registration, SERVICE_WORKER_OK, callback); 1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Return asyncly to simulate having had to look in the db since this 1790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // origin does have some registations. 1805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CompleteFindSoon( 1815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu FROM_HERE, null_registration, SERVICE_WORKER_ERROR_NOT_FOUND, callback); 182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 184effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ServiceWorkerStorage::FindRegistrationForId( 185effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int64 registration_id, 186effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const FindRegistrationCallback& callback) { 1870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch simulated_lazy_initted_ = true; 1880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_refptr<ServiceWorkerRegistration> null_registration; 1890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!context_) { 1900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CompleteFindNow(null_registration, SERVICE_WORKER_ERROR_FAILED, callback); 1910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_refptr<ServiceWorkerRegistration> installing_registration = 1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FindInstallingRegistrationForId(registration_id); 1950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (installing_registration) { 1960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CompleteFindNow(installing_registration, SERVICE_WORKER_OK, callback); 1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RegistrationPtrMap::const_iterator found = 2000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch registrations_by_id_.find(registration_id); 2010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (found == registrations_by_id_.end()) { 2020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CompleteFindNow(null_registration, SERVICE_WORKER_ERROR_NOT_FOUND, 2030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch callback); 2040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 2050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_refptr<ServiceWorkerRegistration> registration = 2070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch context_->GetLiveRegistration(registration_id); 2080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (registration) { 2090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CompleteFindNow(registration, SERVICE_WORKER_OK, callback); 2100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 2110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch registration = CreateRegistration(found->second); 2135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CompleteFindSoon(FROM_HERE, registration, SERVICE_WORKER_OK, callback); 2140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 2150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ServiceWorkerStorage::GetAllRegistrations( 2170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const GetAllRegistrationInfosCallback& callback) { 2180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch simulated_lazy_initted_ = true; 2190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<ServiceWorkerRegistrationInfo> registrations; 2200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!context_) { 2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu RunSoon(FROM_HERE, base::Bind(callback, registrations)); 2220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 2230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Add all stored registrations. 2260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (RegistrationPtrMap::const_iterator it = registrations_by_id_.begin(); 2270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it != registrations_by_id_.end(); ++it) { 2280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ServiceWorkerRegistration* registration = 2290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch context_->GetLiveRegistration(it->first); 2300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (registration) { 2310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch registrations.push_back(registration->GetInfo()); 2320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch continue; 233effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 2340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ServiceWorkerRegistrationInfo info; 2350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch info.pattern = it->second->scope; 2360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch info.script_url = it->second->script; 2370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch info.active_version.is_null = false; 2380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (it->second->is_active) 2390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch info.active_version.status = ServiceWorkerVersion::ACTIVE; 2400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch else 2410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch info.active_version.status = ServiceWorkerVersion::INSTALLED; 2420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch registrations.push_back(info); 2430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Add unstored registrations that are being installed. 2460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (RegistrationRefsById::const_iterator it = 2470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch installing_registrations_.begin(); 2480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it != installing_registrations_.end(); ++it) { 2490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (registrations_by_id_.find(it->first) == registrations_by_id_.end()) 2500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch registrations.push_back(it->second->GetInfo()); 251effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 2520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu RunSoon(FROM_HERE, base::Bind(callback, registrations)); 254effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 255effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerStorage::StoreRegistration( 257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ServiceWorkerRegistration* registration, 2580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ServiceWorkerVersion* version, 259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const StatusCallback& callback) { 260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(registration); 2610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(version); 2620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(simulated_lazy_initted_); 2630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!context_) { 2645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED)); 265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 266a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 2680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Keep a database struct in the storage map. 2690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RegistrationsMap& storage_map = 2700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch stored_registrations_[registration->script_url().GetOrigin()]; 2710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ServiceWorkerDatabase::RegistrationData& data = 2720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch storage_map[registration->id()]; 2730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch data.registration_id = registration->id(); 2740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch data.scope = registration->pattern(); 2750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch data.script = registration->script_url(); 2760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch data.has_fetch_handler = true; 2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch data.version_id = version->version_id(); 2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch data.last_update_check = base::Time::Now(); 2790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch data.is_active = false; // initially stored in the waiting state 2800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Keep a seperate map of ptrs keyed by id only. 2820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch registrations_by_id_[registration->id()] = &storage_map[registration->id()]; 2830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_OK)); 2850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 2860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch void ServiceWorkerStorage::UpdateToActiveState( 2880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ServiceWorkerRegistration* registration, 2890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const StatusCallback& callback) { 2900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(simulated_lazy_initted_); 2910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!context_) { 2925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED)); 2930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 2940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RegistrationPtrMap::const_iterator 2970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch found = registrations_by_id_.find(registration->id()); 2980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (found == registrations_by_id_.end()) { 2995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_NOT_FOUND)); 3000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 3010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!found->second->is_active); 3030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch found->second->is_active = true; 3045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_OK)); 305a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 306a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerStorage::DeleteRegistration( 3080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 registration_id, 309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const StatusCallback& callback) { 3100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(simulated_lazy_initted_); 3110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RegistrationPtrMap::iterator 3120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch found = registrations_by_id_.find(registration_id); 3130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (found == registrations_by_id_.end()) { 3145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_NOT_FOUND)); 315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 316a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 3170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch GURL origin = found->second->script.GetOrigin(); 3190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch stored_registrations_[origin].erase(registration_id); 3200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (stored_registrations_[origin].empty()) 3210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch stored_registrations_.erase(origin); 3220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch registrations_by_id_.erase(found); 3240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_OK)); 3260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // TODO(michaeln): Either its instance should also be 3270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // removed from liveregistrations map or the live object 3280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // should marked as deleted in some way and not 'findable' 3290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // thereafter. 330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int64 ServiceWorkerStorage::NewRegistrationId() { 3330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(simulated_lazy_initted_); 334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return ++last_registration_id_; 335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 337a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int64 ServiceWorkerStorage::NewVersionId() { 3380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(simulated_lazy_initted_); 339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return ++last_version_id_; 340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 3420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint64 ServiceWorkerStorage::NewResourceId() { 3430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(simulated_lazy_initted_); 3440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return ++last_resource_id_; 3450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 3460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ServiceWorkerStorage::NotifyInstallingRegistration( 3480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ServiceWorkerRegistration* registration) { 3490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch installing_registrations_[registration->id()] = registration; 3500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 3510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ServiceWorkerStorage::NotifyDoneInstallingRegistration( 3530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ServiceWorkerRegistration* registration) { 3540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch installing_registrations_.erase(registration->id()); 3550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 3560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochscoped_refptr<ServiceWorkerRegistration> 3580529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerStorage::CreateRegistration( 3590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const ServiceWorkerDatabase::RegistrationData* data) { 3600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_refptr<ServiceWorkerRegistration> registration( 3610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new ServiceWorkerRegistration( 3620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch data->scope, data->script, data->registration_id, context_)); 3630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_refptr<ServiceWorkerVersion> version = 3650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch context_->GetLiveVersion(data->version_id); 3660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!version) { 3670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version = new ServiceWorkerVersion( 3680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch registration, data->version_id, context_); 3690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch version->SetStatus(data->GetVersionStatus()); 3700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (version->status() == ServiceWorkerVersion::ACTIVE) 3730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch registration->set_active_version(version); 3740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch else if (version->status() == ServiceWorkerVersion::INSTALLED) 3750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch registration->set_pending_version(version); 3760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch else 3770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch NOTREACHED(); 3780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // TODO(michaeln): Hmmm, what if DeleteReg was invoked after 3790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // the Find result we're returning here? NOTREACHED condition? 3800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return registration; 3820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 3830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3840529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerRegistration* 3850529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerStorage::FindInstallingRegistrationForDocument( 3860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const GURL& document_url) { 3870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // TODO(michaeln): if there are multiple matches the one with 3880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // the longest scope should win, and these should on equal footing 3890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // with the stored registrations in FindRegistrationForDocument(). 3900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (RegistrationRefsById::const_iterator it = 3910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch installing_registrations_.begin(); 3920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it != installing_registrations_.end(); ++it) { 3930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (ServiceWorkerUtils::ScopeMatches( 3940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it->second->pattern(), document_url)) { 3950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return it->second; 3960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return NULL; 3990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 4000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4010529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerRegistration* 4020529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerStorage::FindInstallingRegistrationForPattern( 4030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const GURL& scope) { 4040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (RegistrationRefsById::const_iterator it = 4050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch installing_registrations_.begin(); 4060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it != installing_registrations_.end(); ++it) { 4070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (it->second->pattern() == scope) 4080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return it->second; 4090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return NULL; 4110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 4120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4130529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerRegistration* 4140529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerStorage::FindInstallingRegistrationForId( 4150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int64 registration_id) { 4160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RegistrationRefsById::const_iterator found = 4170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch installing_registrations_.find(registration_id); 4180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (found == installing_registrations_.end()) 4190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return NULL; 4200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return found->second; 4210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 4220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 423a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace content 424