OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/background_fetch/background_fetch_data_manager.h" | 5 #include "content/browser/background_fetch/background_fetch_data_manager.h" |
6 | 6 |
| 7 #include <algorithm> |
7 #include <queue> | 8 #include <queue> |
8 | 9 |
9 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
10 #include "content/browser/background_fetch/background_fetch_constants.h" | 11 #include "content/browser/background_fetch/background_fetch_constants.h" |
11 #include "content/browser/background_fetch/background_fetch_context.h" | 12 #include "content/browser/background_fetch/background_fetch_context.h" |
12 #include "content/browser/background_fetch/background_fetch_job_response_data.h" | |
13 #include "content/browser/background_fetch/background_fetch_request_info.h" | 13 #include "content/browser/background_fetch/background_fetch_request_info.h" |
14 #include "content/browser/blob_storage/chrome_blob_storage_context.h" | 14 #include "content/browser/blob_storage/chrome_blob_storage_context.h" |
15 #include "content/public/browser/blob_handle.h" | 15 #include "content/public/browser/blob_handle.h" |
16 #include "content/public/browser/browser_context.h" | 16 #include "content/public/browser/browser_context.h" |
17 #include "content/public/browser/download_interrupt_reasons.h" | 17 #include "content/public/browser/download_interrupt_reasons.h" |
18 #include "content/public/browser/download_item.h" | 18 #include "content/public/browser/download_item.h" |
19 | 19 |
20 namespace content { | 20 namespace content { |
21 | 21 |
22 // The Registration Data class encapsulates the data stored for a particular | 22 // The Registration Data class encapsulates the data stored for a particular |
23 // Background Fetch registration. This roughly matches the on-disk format that | 23 // Background Fetch registration. This roughly matches the on-disk format that |
24 // will be adhered to in the future. | 24 // will be adhered to in the future. |
25 class BackgroundFetchDataManager::RegistrationData { | 25 class BackgroundFetchDataManager::RegistrationData { |
26 public: | 26 public: |
27 RegistrationData(const std::vector<ServiceWorkerFetchRequest>& requests, | 27 RegistrationData(const std::vector<ServiceWorkerFetchRequest>& requests, |
28 const BackgroundFetchOptions& options) | 28 const BackgroundFetchOptions& options) |
29 : options_(options) { | 29 : options_(options) { |
30 int request_index = 0; | 30 int request_index = 0; |
31 | 31 |
32 // Convert the given |requests| to BackgroundFetchRequestInfo objects. | 32 // Convert the given |requests| to BackgroundFetchRequestInfo objects. |
33 for (const ServiceWorkerFetchRequest& request : requests) | 33 for (const ServiceWorkerFetchRequest& request : requests) |
34 requests_.emplace(request_index++, request); | 34 pending_requests_.emplace(request_index++, request); |
35 } | 35 } |
36 | 36 |
37 ~RegistrationData() = default; | 37 ~RegistrationData() = default; |
38 | 38 |
39 // Returns whether there are remaining requests on the request queue. | 39 // Returns whether there are remaining requests on the request queue. |
40 bool HasPendingRequests() const { return !requests_.empty(); } | 40 bool HasPendingRequests() const { return !pending_requests_.empty(); } |
41 | 41 |
42 // Consumes a request from the queue that is to be fetched. | 42 // Consumes a request from the queue that is to be fetched. |
43 BackgroundFetchRequestInfo ConsumeRequest() { | 43 BackgroundFetchRequestInfo GetPendingRequest() { |
44 DCHECK(!requests_.empty()); | 44 DCHECK(!pending_requests_.empty()); |
45 | 45 |
46 BackgroundFetchRequestInfo request = requests_.front(); | 46 BackgroundFetchRequestInfo request = pending_requests_.front(); |
47 requests_.pop(); | 47 pending_requests_.pop(); |
| 48 |
| 49 // The |request| is considered to be active now. |
| 50 active_requests_.push_back(request); |
48 | 51 |
49 return request; | 52 return request; |
50 } | 53 } |
51 | 54 |
| 55 // Marks the |request| as having started with the given |download_guid|. |
| 56 // Persistent storage needs to store the association so we can resume fetches |
| 57 // after a browser restart, here we just verify that the |request| is active. |
| 58 void MarkRequestAsStarted(const BackgroundFetchRequestInfo& request, |
| 59 const std::string& download_guid) { |
| 60 const auto iter = std::find_if( |
| 61 active_requests_.begin(), active_requests_.end(), |
| 62 [&request](const BackgroundFetchRequestInfo& active_request) { |
| 63 return active_request.request_index() == request.request_index(); |
| 64 }); |
| 65 |
| 66 // The |request| must have been consumed from this RegistrationData. |
| 67 DCHECK(iter != active_requests_.end()); |
| 68 } |
| 69 |
| 70 // Marks the |request| as having completed. Verifies that the |request| is |
| 71 // currently active and moves it to the |completed_requests_| vector. |
| 72 void MarkRequestAsComplete(const BackgroundFetchRequestInfo& request) { |
| 73 const auto iter = std::find_if( |
| 74 active_requests_.begin(), active_requests_.end(), |
| 75 [&request](const BackgroundFetchRequestInfo& active_request) { |
| 76 return active_request.request_index() == request.request_index(); |
| 77 }); |
| 78 |
| 79 // The |request| must have been consumed from this RegistrationData. |
| 80 DCHECK(iter != active_requests_.end()); |
| 81 |
| 82 active_requests_.erase(iter); |
| 83 completed_requests_.push_back(request); |
| 84 } |
| 85 |
| 86 // Returns the vector with all completed requests part of this registration. |
| 87 const std::vector<BackgroundFetchRequestInfo>& GetCompletedRequests() const { |
| 88 return completed_requests_; |
| 89 } |
| 90 |
52 private: | 91 private: |
53 std::queue<BackgroundFetchRequestInfo> requests_; | |
54 BackgroundFetchOptions options_; | 92 BackgroundFetchOptions options_; |
55 | 93 |
| 94 // TODO(peter): BackgroundFetchRequestInfo should be stored in a |
| 95 // unique_ptr, owned by the BackgroundFetchJobController. Right now we |
| 96 // can't do that as we need to hold on to copies here. |
| 97 std::queue<BackgroundFetchRequestInfo> pending_requests_; |
| 98 std::vector<BackgroundFetchRequestInfo> active_requests_; |
| 99 |
| 100 // TODO(peter): Right now it's safe for this to be a vector because we only |
| 101 // allow a single parallel request. That stops when we start allowing more. |
| 102 static_assert(kMaximumBackgroundFetchParallelRequests == 1, |
| 103 "RegistrationData::completed_requests_ assumes no parallelism"); |
| 104 |
| 105 std::vector<BackgroundFetchRequestInfo> completed_requests_; |
| 106 |
56 DISALLOW_COPY_AND_ASSIGN(RegistrationData); | 107 DISALLOW_COPY_AND_ASSIGN(RegistrationData); |
57 }; | 108 }; |
58 | 109 |
59 BackgroundFetchDataManager::BackgroundFetchDataManager( | 110 BackgroundFetchDataManager::BackgroundFetchDataManager( |
60 BrowserContext* browser_context) | 111 BrowserContext* browser_context) |
61 : browser_context_(browser_context), weak_ptr_factory_(this) { | 112 : weak_ptr_factory_(this) { |
62 DCHECK(browser_context_); | 113 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 114 DCHECK(browser_context); |
| 115 |
| 116 // Store the blob storage context for the given |browser_context|. |
| 117 blob_storage_context_ = |
| 118 make_scoped_refptr(ChromeBlobStorageContext::GetFor(browser_context)); |
| 119 DCHECK(blob_storage_context_); |
63 } | 120 } |
64 | 121 |
65 BackgroundFetchDataManager::~BackgroundFetchDataManager() = default; | 122 BackgroundFetchDataManager::~BackgroundFetchDataManager() = default; |
66 | 123 |
67 void BackgroundFetchDataManager::CreateRegistration( | 124 void BackgroundFetchDataManager::CreateRegistration( |
68 const BackgroundFetchRegistrationId& registration_id, | 125 const BackgroundFetchRegistrationId& registration_id, |
69 const std::vector<ServiceWorkerFetchRequest>& requests, | 126 const std::vector<ServiceWorkerFetchRequest>& requests, |
70 const BackgroundFetchOptions& options, | 127 const BackgroundFetchOptions& options, |
71 CreateRegistrationCallback callback) { | 128 CreateRegistrationCallback callback) { |
72 if (registrations_.find(registration_id) != registrations_.end()) { | 129 if (registrations_.find(registration_id) != registrations_.end()) { |
73 std::move(callback).Run(blink::mojom::BackgroundFetchError::DUPLICATED_TAG, | 130 std::move(callback).Run(blink::mojom::BackgroundFetchError::DUPLICATED_TAG, |
74 std::vector<BackgroundFetchRequestInfo>()); | 131 std::vector<BackgroundFetchRequestInfo>()); |
75 return; | 132 return; |
76 } | 133 } |
77 | 134 |
78 std::unique_ptr<RegistrationData> registration_data = | 135 std::unique_ptr<RegistrationData> registration_data = |
79 base::MakeUnique<RegistrationData>(requests, options); | 136 base::MakeUnique<RegistrationData>(requests, options); |
80 | 137 |
81 // Create a vector with the initial requests to feed the Job Controller with. | 138 // Create a vector with the initial requests to feed the Job Controller with. |
82 std::vector<BackgroundFetchRequestInfo> initial_requests; | 139 std::vector<BackgroundFetchRequestInfo> initial_requests; |
83 for (size_t i = 0; i < kMaximumBackgroundFetchParallelRequests; ++i) { | 140 for (size_t i = 0; i < kMaximumBackgroundFetchParallelRequests; ++i) { |
84 if (!registration_data->HasPendingRequests()) | 141 if (!registration_data->HasPendingRequests()) |
85 break; | 142 break; |
86 | 143 |
87 initial_requests.push_back(registration_data->ConsumeRequest()); | 144 initial_requests.push_back(registration_data->GetPendingRequest()); |
88 } | 145 } |
89 | 146 |
90 // Store the created |registration_data| so that we can easily access it. | 147 // Store the created |registration_data| so that we can easily access it. |
91 registrations_.insert( | 148 registrations_.insert( |
92 std::make_pair(registration_id, std::move(registration_data))); | 149 std::make_pair(registration_id, std::move(registration_data))); |
93 | 150 |
94 // Inform the |callback| of the newly created registration. | 151 // Inform the |callback| of the newly created registration. |
95 std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE, | 152 std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE, |
96 std::move(initial_requests)); | 153 std::move(initial_requests)); |
97 } | 154 } |
98 | 155 |
99 void BackgroundFetchDataManager::MarkRequestAsStarted( | 156 void BackgroundFetchDataManager::MarkRequestAsStarted( |
100 const BackgroundFetchRegistrationId& registration_id, | 157 const BackgroundFetchRegistrationId& registration_id, |
101 const BackgroundFetchRequestInfo& request, | 158 const BackgroundFetchRequestInfo& request, |
102 const std::string& download_guid) { | 159 const std::string& download_guid) { |
103 auto iter = registrations_.find(registration_id); | 160 auto iter = registrations_.find(registration_id); |
104 DCHECK(iter != registrations_.end()); | 161 DCHECK(iter != registrations_.end()); |
105 | 162 |
106 // TODO(peter): Associate the |download_guid| with the |request|. | 163 RegistrationData* registration_data = iter->second.get(); |
| 164 registration_data->MarkRequestAsStarted(request, download_guid); |
107 } | 165 } |
108 | 166 |
109 void BackgroundFetchDataManager::MarkRequestAsCompleteAndGetNextRequest( | 167 void BackgroundFetchDataManager::MarkRequestAsCompleteAndGetNextRequest( |
110 const BackgroundFetchRegistrationId& registration_id, | 168 const BackgroundFetchRegistrationId& registration_id, |
111 const BackgroundFetchRequestInfo& request, | 169 const BackgroundFetchRequestInfo& request, |
112 NextRequestCallback callback) { | 170 NextRequestCallback callback) { |
113 auto iter = registrations_.find(registration_id); | 171 auto iter = registrations_.find(registration_id); |
114 DCHECK(iter != registrations_.end()); | 172 DCHECK(iter != registrations_.end()); |
115 | 173 |
116 RegistrationData* registration_data = iter->second.get(); | 174 RegistrationData* registration_data = iter->second.get(); |
117 | 175 registration_data->MarkRequestAsComplete(request); |
118 // TODO(peter): Store the |request| with the |registration_data|. | |
119 | 176 |
120 base::Optional<BackgroundFetchRequestInfo> next_request; | 177 base::Optional<BackgroundFetchRequestInfo> next_request; |
121 if (registration_data->HasPendingRequests()) | 178 if (registration_data->HasPendingRequests()) |
122 next_request = registration_data->ConsumeRequest(); | 179 next_request = registration_data->GetPendingRequest(); |
123 | 180 |
124 std::move(callback).Run(next_request); | 181 std::move(callback).Run(next_request); |
125 } | 182 } |
126 | 183 |
| 184 void BackgroundFetchDataManager::GetSettledFetchesForRegistration( |
| 185 const BackgroundFetchRegistrationId& registration_id, |
| 186 SettledFetchesCallback callback) { |
| 187 auto iter = registrations_.find(registration_id); |
| 188 DCHECK(iter != registrations_.end()); |
| 189 |
| 190 RegistrationData* registration_data = iter->second.get(); |
| 191 DCHECK(!registration_data->HasPendingRequests()); |
| 192 |
| 193 const std::vector<BackgroundFetchRequestInfo>& requests = |
| 194 registration_data->GetCompletedRequests(); |
| 195 |
| 196 std::vector<BackgroundFetchSettledFetch> settled_fetches; |
| 197 settled_fetches.reserve(requests.size()); |
| 198 |
| 199 std::vector<std::unique_ptr<BlobHandle>> blob_handles; |
| 200 |
| 201 for (const auto& request : requests) { |
| 202 BackgroundFetchSettledFetch settled_fetch; |
| 203 settled_fetch.request = request.fetch_request(); |
| 204 |
| 205 settled_fetch.response.url_list.push_back(request.GetURL()); |
| 206 // TODO: settled_fetch.response.status_code |
| 207 // TODO: settled_fetch.response.status_text |
| 208 // TODO: settled_fetch.response.response_type |
| 209 // TODO: settled_fetch.response.headers |
| 210 |
| 211 if (request.received_bytes() > 0) { |
| 212 DCHECK(!request.file_path().empty()); |
| 213 |
| 214 std::unique_ptr<BlobHandle> blob_handle = |
| 215 blob_storage_context_->CreateFileBackedBlob( |
| 216 request.file_path(), 0 /* offset */, request.received_bytes(), |
| 217 base::Time() /* expected_modification_time */); |
| 218 |
| 219 // TODO(peter): Appropriately handle !blob_handle |
| 220 if (blob_handle) { |
| 221 settled_fetch.response.blob_uuid = blob_handle->GetUUID(); |
| 222 settled_fetch.response.blob_size = request.received_bytes(); |
| 223 |
| 224 blob_handles.push_back(std::move(blob_handle)); |
| 225 } |
| 226 } |
| 227 |
| 228 // TODO: settled_fetch.response.error |
| 229 // TODO: settled_fetch.response.response_time |
| 230 // TODO: settled_fetch.response.cors_exposed_header_names |
| 231 |
| 232 settled_fetches.push_back(settled_fetch); |
| 233 } |
| 234 |
| 235 std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE, |
| 236 std::move(settled_fetches), std::move(blob_handles)); |
| 237 } |
| 238 |
127 void BackgroundFetchDataManager::DeleteRegistration( | 239 void BackgroundFetchDataManager::DeleteRegistration( |
128 const BackgroundFetchRegistrationId& registration_id, | 240 const BackgroundFetchRegistrationId& registration_id, |
129 DeleteRegistrationCallback callback) { | 241 DeleteRegistrationCallback callback) { |
130 auto iter = registrations_.find(registration_id); | 242 auto iter = registrations_.find(registration_id); |
131 if (iter == registrations_.end()) { | 243 if (iter == registrations_.end()) { |
132 std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_TAG); | 244 std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_TAG); |
133 return; | 245 return; |
134 } | 246 } |
135 | 247 |
136 registrations_.erase(iter); | 248 registrations_.erase(iter); |
137 | 249 |
138 std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE); | 250 std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE); |
139 } | 251 } |
140 | 252 |
141 void BackgroundFetchDataManager::WriteJobToStorage( | |
142 std::unique_ptr<BackgroundFetchJobInfo> job_info, | |
143 std::vector<std::unique_ptr<BackgroundFetchRequestInfo>> request_infos) { | |
144 // TODO(harkness): Check for job_guid clash. | |
145 const std::string job_guid = job_info->guid(); | |
146 job_map_[job_guid] = std::move(job_info); | |
147 | |
148 // Make an explicit copy of the original requests | |
149 // TODO(harkness): Replace this with actually writing to storage. | |
150 std::vector<BackgroundFetchRequestInfo> requests; | |
151 for (const auto& request_info : request_infos) { | |
152 requests.emplace_back(*(request_info.get())); | |
153 } | |
154 request_map_[job_guid] = std::move(requests); | |
155 | |
156 // |request_infos| will be destroyed when it leaves scope here. | |
157 } | |
158 | |
159 void BackgroundFetchDataManager::WriteRequestToStorage( | |
160 const std::string& job_guid, | |
161 BackgroundFetchRequestInfo* request_info) { | |
162 std::vector<BackgroundFetchRequestInfo>& request_infos = | |
163 request_map_[job_guid]; | |
164 | |
165 // Copy the updated |request_info| over the in-memory version. | |
166 for (size_t i = 0; i < request_infos.size(); i++) { | |
167 if (request_infos[i].guid() == request_info->guid()) | |
168 request_infos[i] = *request_info; | |
169 } | |
170 } | |
171 | |
172 std::unique_ptr<BackgroundFetchRequestInfo> | |
173 BackgroundFetchDataManager::GetRequestInfo(const std::string& job_guid, | |
174 size_t request_index) { | |
175 // Explicitly create a copy. When this is persisted to StorageWorkerStorage, | |
176 // the request_map_ will not exist. | |
177 auto iter = request_map_.find(job_guid); | |
178 DCHECK(iter != request_map_.end()); | |
179 const std::vector<BackgroundFetchRequestInfo>& request_infos = iter->second; | |
180 | |
181 DCHECK(request_index <= request_infos.size()); | |
182 return base::MakeUnique<BackgroundFetchRequestInfo>( | |
183 request_infos[request_index]); | |
184 } | |
185 | |
186 void BackgroundFetchDataManager::GetJobResponse( | |
187 const std::string& job_guid, | |
188 const BackgroundFetchResponseCompleteCallback& callback) { | |
189 BrowserThread::PostTaskAndReplyWithResult( | |
190 BrowserThread::UI, FROM_HERE, | |
191 base::Bind(&ChromeBlobStorageContext::GetFor, browser_context_), | |
192 base::Bind(&BackgroundFetchDataManager::DidGetBlobStorageContext, | |
193 weak_ptr_factory_.GetWeakPtr(), job_guid, callback)); | |
194 } | |
195 | |
196 void BackgroundFetchDataManager::DidGetBlobStorageContext( | |
197 const std::string& job_guid, | |
198 const BackgroundFetchResponseCompleteCallback& callback, | |
199 ChromeBlobStorageContext* blob_context) { | |
200 DCHECK(blob_context); | |
201 BackgroundFetchJobInfo* job_info = job_map_[job_guid].get(); | |
202 DCHECK(job_info); | |
203 | |
204 // Create a BackgroundFetchJobResponseData object which will aggregate | |
205 // together the response blobs. | |
206 job_info->set_job_response_data( | |
207 base::MakeUnique<BackgroundFetchJobResponseData>(job_info->num_requests(), | |
208 callback)); | |
209 BackgroundFetchJobResponseData* job_response_data = | |
210 job_info->job_response_data(); | |
211 DCHECK(job_response_data); | |
212 | |
213 // Iterate over the requests and create blobs for each response. | |
214 for (size_t request_index = 0; request_index < job_info->num_requests(); | |
215 request_index++) { | |
216 // TODO(harkness): This will need to be asynchronous. | |
217 std::unique_ptr<BackgroundFetchRequestInfo> request_info = | |
218 GetRequestInfo(job_guid, request_index); | |
219 | |
220 // TODO(harkness): Only create a blob response if the request was | |
221 // successful. Otherwise create an error response. | |
222 std::unique_ptr<BlobHandle> blob_handle = | |
223 blob_context->CreateFileBackedBlob( | |
224 request_info->file_path(), 0 /* offset */, | |
225 request_info->received_bytes(), | |
226 base::Time() /* expected_modification_time */); | |
227 | |
228 job_response_data->AddResponse(*request_info.get(), std::move(blob_handle)); | |
229 } | |
230 } | |
231 | |
232 bool BackgroundFetchDataManager::UpdateRequestState( | |
233 const std::string& job_guid, | |
234 const std::string& request_guid, | |
235 DownloadItem::DownloadState state, | |
236 DownloadInterruptReason interrupt_reason) { | |
237 // Find the request and set the state and the interrupt reason. | |
238 BackgroundFetchJobInfo* job_info = job_map_[job_guid].get(); | |
239 DCHECK(job_info); | |
240 BackgroundFetchRequestInfo* request = | |
241 job_info->GetActiveRequest(request_guid); | |
242 DCHECK(request); | |
243 request->set_state(state); | |
244 request->set_interrupt_reason(interrupt_reason); | |
245 | |
246 // If the request is now finished, remove it from the active requests. | |
247 switch (state) { | |
248 case DownloadItem::DownloadState::COMPLETE: | |
249 case DownloadItem::DownloadState::CANCELLED: | |
250 WriteRequestToStorage(job_guid, request); | |
251 job_info->RemoveActiveRequest(request_guid); | |
252 break; | |
253 case DownloadItem::DownloadState::IN_PROGRESS: | |
254 case DownloadItem::DownloadState::INTERRUPTED: | |
255 case DownloadItem::DownloadState::MAX_DOWNLOAD_STATE: | |
256 break; | |
257 } | |
258 | |
259 // Return a boolean indicating whether there are more requests to be | |
260 // processed. | |
261 return job_info->HasRequestsRemaining(); | |
262 } | |
263 | |
264 void BackgroundFetchDataManager::UpdateRequestStorageState( | |
265 const std::string& job_guid, | |
266 const std::string& request_guid, | |
267 const base::FilePath& file_path, | |
268 int64_t received_bytes) { | |
269 BackgroundFetchJobInfo* job_info = job_map_[job_guid].get(); | |
270 DCHECK(job_info); | |
271 BackgroundFetchRequestInfo* request = | |
272 job_info->GetActiveRequest(request_guid); | |
273 DCHECK(request); | |
274 request->set_file_path(file_path); | |
275 request->set_received_bytes(received_bytes); | |
276 } | |
277 | |
278 const BackgroundFetchRequestInfo& | |
279 BackgroundFetchDataManager::GetNextBackgroundFetchRequestInfo( | |
280 const std::string& job_guid) { | |
281 BackgroundFetchJobInfo* job_info = job_map_[job_guid].get(); | |
282 DCHECK(job_info); | |
283 | |
284 // TODO(harkness): This needs to be async when it queries real storage. | |
285 std::unique_ptr<BackgroundFetchRequestInfo> request_info = | |
286 GetRequestInfo(job_guid, job_info->next_request_index()); | |
287 const std::string request_guid = request_info->guid(); | |
288 job_info->AddActiveRequest(std::move(request_info)); | |
289 return *job_info->GetActiveRequest(request_guid); | |
290 } | |
291 | |
292 bool BackgroundFetchDataManager::IsComplete(const std::string& job_guid) const { | |
293 auto iter = job_map_.find(job_guid); | |
294 DCHECK(iter != job_map_.end()); | |
295 return iter->second->IsComplete(); | |
296 } | |
297 | |
298 bool BackgroundFetchDataManager::HasRequestsRemaining( | |
299 const std::string& job_guid) const { | |
300 auto iter = job_map_.find(job_guid); | |
301 DCHECK(iter != job_map_.end()); | |
302 return iter->second->HasRequestsRemaining(); | |
303 } | |
304 | |
305 void BackgroundFetchDataManager::UpdateRequestDownloadGuid( | |
306 const std::string& job_guid, | |
307 const std::string& request_guid, | |
308 const std::string& download_guid) { | |
309 BackgroundFetchJobInfo* job_info = job_map_[job_guid].get(); | |
310 DCHECK(job_info); | |
311 BackgroundFetchRequestInfo* request = | |
312 job_info->GetActiveRequest(request_guid); | |
313 DCHECK(request); | |
314 request->set_download_guid(download_guid); | |
315 } | |
316 | |
317 } // namespace content | 253 } // namespace content |
OLD | NEW |