OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "content/browser/appcache/appcache_executable_handler_impl.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/lazy_instance.h" |
| 9 #include "base/strings/stringprintf.h" |
| 10 #include "base/message_loop/message_loop.h" |
| 11 #include "content/browser/fileapi/chrome_blob_storage_context.h" |
| 12 #include "content/browser/worker_host/worker_service_impl.h" |
| 13 #include "content/common/worker_messages.h" |
| 14 #include "net/url_request/url_request.h" |
| 15 #include "content/common/appcache_messages.h" |
| 16 |
| 17 namespace content { |
| 18 |
| 19 namespace { |
| 20 int g_last_request_id = 0; |
| 21 |
| 22 typedef std::map<int, AppCacheExecutableHandlerImpl::ResponseCallback> |
| 23 CallbackMap; |
| 24 |
| 25 base::LazyInstance<CallbackMap>::Leaky g_pending_response_callbacks = |
| 26 LAZY_INSTANCE_INITIALIZER; |
| 27 |
| 28 |
| 29 CallbackMap& callback_map() { |
| 30 return g_pending_response_callbacks.Get(); |
| 31 } |
| 32 } // namespace |
| 33 |
| 34 AppCacheExecutableHandlerFactoryImpl::AppCacheExecutableHandlerFactoryImpl( |
| 35 ResourceContext* resource_context, const WorkerStoragePartition& partition, |
| 36 ChromeBlobStorageContext* blob_context) |
| 37 : resource_context_(resource_context), partition_(partition), |
| 38 blob_context_(blob_context) { |
| 39 // To avoid reference cycles we don't store a reference to the appcache_servic
e. |
| 40 appcache_service_ = partition.appcache_service(); |
| 41 partition_ = WorkerStoragePartition( |
| 42 partition.url_request_context(), |
| 43 partition.media_url_request_context(), |
| 44 NULL, |
| 45 partition.quota_manager(), |
| 46 partition.filesystem_context(), |
| 47 partition.database_tracker(), |
| 48 partition.indexed_db_context()); |
| 49 } |
| 50 |
| 51 AppCacheExecutableHandlerFactoryImpl::~AppCacheExecutableHandlerFactoryImpl() { |
| 52 } |
| 53 |
| 54 scoped_ptr<appcache::AppCacheExecutableHandler> |
| 55 AppCacheExecutableHandlerFactoryImpl::CreateHandler( |
| 56 int64 appcache_id, |
| 57 const GURL& handler_url, |
| 58 const std::string& raw_handler_source) { |
| 59 // Construct a partition that includes a reference to the appcache service. |
| 60 return scoped_ptr<appcache::AppCacheExecutableHandler>( |
| 61 new AppCacheExecutableHandlerImpl(appcache_id, handler_url, raw_handler_so
urce, |
| 62 resource_context_, appcache_service_, &p
artition_)); |
| 63 } |
| 64 |
| 65 webkit_blob::BlobStorageController* |
| 66 AppCacheExecutableHandlerFactoryImpl::GetBlobStorageController() { |
| 67 return blob_context_->controller(); |
| 68 } |
| 69 |
| 70 fileapi::FileSystemContext* |
| 71 AppCacheExecutableHandlerFactoryImpl::GetFileSystemContext() { |
| 72 return partition_.filesystem_context(); |
| 73 } |
| 74 |
| 75 AppCacheExecutableHandlerImpl::AppCacheExecutableHandlerImpl( |
| 76 int64 appcache_id, |
| 77 const GURL& handler_url, |
| 78 const std::string& raw_handler_source, |
| 79 ResourceContext* resource_context, |
| 80 ChromeAppCacheService* appcache_service, |
| 81 WorkerStoragePartition* partition) : |
| 82 worker_route_id_(-1), |
| 83 appcache_id_(appcache_id), |
| 84 handler_url_(handler_url), |
| 85 raw_handler_source_(raw_handler_source), |
| 86 resource_context_(resource_context), |
| 87 appcache_service_(appcache_service), |
| 88 partition_(partition) { |
| 89 EnsureWorkerStarted(); |
| 90 } |
| 91 |
| 92 void AppCacheExecutableHandlerImpl::EnsureWorkerStarted() { |
| 93 if (worker_route_id_ != -1) |
| 94 return; |
| 95 |
| 96 WorkerStoragePartition partition( |
| 97 partition_->url_request_context(), |
| 98 partition_->media_url_request_context(), |
| 99 appcache_service_, |
| 100 partition_->quota_manager(), |
| 101 partition_->filesystem_context(), |
| 102 partition_->database_tracker(), |
| 103 partition_->indexed_db_context()); |
| 104 |
| 105 worker_route_id_ = WorkerServiceImpl::GetInstance()-> |
| 106 CreateAndStartEmbeddedWorker(resource_context_, partition, handler_url_, |
| 107 raw_handler_source_, appcache_id_); |
| 108 WorkerServiceImpl::GetInstance()->AddObserver(this); |
| 109 } |
| 110 |
| 111 AppCacheExecutableHandlerImpl::~AppCacheExecutableHandlerImpl() { |
| 112 ClearCallbacks(); |
| 113 if (worker_route_id_ != -1) |
| 114 WorkerServiceImpl::GetInstance()->TerminateEmbeddedWorker( |
| 115 worker_route_id_); |
| 116 } |
| 117 |
| 118 void AppCacheExecutableHandlerImpl::HandleRequest( |
| 119 const Request& request, ResponseCallback user_callback) { |
| 120 // Invoke the handler scripts onRequest() method and wait for it to |
| 121 // respondWith something. |
| 122 int request_id = ++g_last_request_id; |
| 123 |
| 124 EnsureWorkerStarted(); |
| 125 |
| 126 WorkerServiceImpl::GetInstance()->SendToEmbeddedWorker( |
| 127 worker_route_id_, |
| 128 new AppCacheMsg_FetchEvent(worker_route_id_, |
| 129 request_id, |
| 130 request)); |
| 131 |
| 132 pending_request_ids_.insert(request_id); |
| 133 callback_map()[request_id] = |
| 134 base::Bind(&AppCacheExecutableHandlerImpl::CallbackAdapter, |
| 135 base::Unretained(this), |
| 136 request_id, user_callback); |
| 137 |
| 138 // TODO(michaeln): start a generous timer to complete the request if |
| 139 // the handler fails to. |
| 140 } |
| 141 |
| 142 void AppCacheExecutableHandlerImpl::CallbackAdapter( |
| 143 int request_id, ResponseCallback user_callback, const Response& resp) { |
| 144 user_callback.Run(resp); |
| 145 pending_request_ids_.erase(request_id); |
| 146 callback_map().erase(request_id); |
| 147 } |
| 148 |
| 149 //static |
| 150 void AppCacheExecutableHandlerImpl::ProcessResponse( |
| 151 int request_id, const Response& resp) { |
| 152 CallbackMap::const_iterator found = callback_map().find(request_id); |
| 153 if (found != callback_map().end()) |
| 154 found->second.Run(resp); // CallbackAdapter() invocation. |
| 155 } |
| 156 |
| 157 void AppCacheExecutableHandlerImpl::WorkerDestroyed(int process_id, int route_id
) { |
| 158 if (route_id != worker_route_id_) |
| 159 return; |
| 160 ClearCallbacks(); |
| 161 worker_route_id_ = -1; |
| 162 } |
| 163 |
| 164 void AppCacheExecutableHandlerImpl::ClearCallbacks() { |
| 165 WorkerServiceImpl::GetInstance()->RemoveObserver(this); |
| 166 for (std::set<int>::const_iterator iter = pending_request_ids_.begin(); |
| 167 iter != pending_request_ids_.end(); ++iter) { |
| 168 callback_map().erase(*iter); |
| 169 } |
| 170 } |
| 171 |
| 172 } // namespace content |
OLD | NEW |