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 <algorithm> |
8 #include <queue> | 8 #include <queue> |
9 | 9 |
10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
(...skipping 12 matching lines...) Expand all Loading... |
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& fetch_request : requests) { |
34 pending_requests_.emplace(request_index++, request); | 34 scoped_refptr<BackgroundFetchRequestInfo> request = |
| 35 new BackgroundFetchRequestInfo(request_index++, fetch_request); |
| 36 |
| 37 pending_requests_.push(std::move(request)); |
| 38 } |
35 } | 39 } |
36 | 40 |
37 ~RegistrationData() = default; | 41 ~RegistrationData() = default; |
38 | 42 |
39 // Returns whether there are remaining requests on the request queue. | 43 // Returns whether there are remaining requests on the request queue. |
40 bool HasPendingRequests() const { return !pending_requests_.empty(); } | 44 bool HasPendingRequests() const { return !pending_requests_.empty(); } |
41 | 45 |
42 // Consumes a request from the queue that is to be fetched. | 46 // Consumes a request from the queue that is to be fetched. |
43 BackgroundFetchRequestInfo GetPendingRequest() { | 47 scoped_refptr<BackgroundFetchRequestInfo> GetPendingRequest() { |
44 DCHECK(!pending_requests_.empty()); | 48 DCHECK(!pending_requests_.empty()); |
45 | 49 |
46 BackgroundFetchRequestInfo request = pending_requests_.front(); | 50 auto request = pending_requests_.front(); |
47 pending_requests_.pop(); | 51 pending_requests_.pop(); |
48 | 52 |
49 // The |request| is considered to be active now. | 53 // The |request| is considered to be active now. |
50 active_requests_.push_back(request); | 54 active_requests_.push_back(request); |
51 | 55 |
52 return request; | 56 return request; |
53 } | 57 } |
54 | 58 |
55 // Marks the |request| as having started with the given |download_guid|. | 59 // Marks the |request| as having started with the given |download_guid|. |
56 // Persistent storage needs to store the association so we can resume fetches | 60 // 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. | 61 // after a browser restart, here we just verify that the |request| is active. |
58 void MarkRequestAsStarted(const BackgroundFetchRequestInfo& request, | 62 void MarkRequestAsStarted(BackgroundFetchRequestInfo* request, |
59 const std::string& download_guid) { | 63 const std::string& download_guid) { |
60 const auto iter = std::find_if( | 64 const auto iter = std::find_if( |
61 active_requests_.begin(), active_requests_.end(), | 65 active_requests_.begin(), active_requests_.end(), |
62 [&request](const BackgroundFetchRequestInfo& active_request) { | 66 [&request](scoped_refptr<BackgroundFetchRequestInfo> active_request) { |
63 return active_request.request_index() == request.request_index(); | 67 return active_request->request_index() == request->request_index(); |
64 }); | 68 }); |
65 | 69 |
66 // The |request| must have been consumed from this RegistrationData. | 70 // The |request| must have been consumed from this RegistrationData. |
67 DCHECK(iter != active_requests_.end()); | 71 DCHECK(iter != active_requests_.end()); |
68 } | 72 } |
69 | 73 |
70 // Marks the |request| as having completed. Verifies that the |request| is | 74 // Marks the |request| as having completed. Verifies that the |request| is |
71 // currently active and moves it to the |completed_requests_| vector. | 75 // currently active and moves it to the |completed_requests_| vector. |
72 void MarkRequestAsComplete(const BackgroundFetchRequestInfo& request) { | 76 void MarkRequestAsComplete(BackgroundFetchRequestInfo* request) { |
73 const auto iter = std::find_if( | 77 const auto iter = std::find_if( |
74 active_requests_.begin(), active_requests_.end(), | 78 active_requests_.begin(), active_requests_.end(), |
75 [&request](const BackgroundFetchRequestInfo& active_request) { | 79 [&request](scoped_refptr<BackgroundFetchRequestInfo> active_request) { |
76 return active_request.request_index() == request.request_index(); | 80 return active_request->request_index() == request->request_index(); |
77 }); | 81 }); |
78 | 82 |
79 // The |request| must have been consumed from this RegistrationData. | 83 // The |request| must have been consumed from this RegistrationData. |
80 DCHECK(iter != active_requests_.end()); | 84 DCHECK(iter != active_requests_.end()); |
81 | 85 |
| 86 completed_requests_.push_back(*iter); |
82 active_requests_.erase(iter); | 87 active_requests_.erase(iter); |
83 completed_requests_.push_back(request); | |
84 } | 88 } |
85 | 89 |
86 // Returns the vector with all completed requests part of this registration. | 90 // Returns the vector with all completed requests part of this registration. |
87 const std::vector<BackgroundFetchRequestInfo>& GetCompletedRequests() const { | 91 const std::vector<scoped_refptr<BackgroundFetchRequestInfo>>& |
| 92 GetCompletedRequests() const { |
88 return completed_requests_; | 93 return completed_requests_; |
89 } | 94 } |
90 | 95 |
91 private: | 96 private: |
92 BackgroundFetchOptions options_; | 97 BackgroundFetchOptions options_; |
93 | 98 |
94 // TODO(peter): BackgroundFetchRequestInfo should be stored in a | 99 std::queue<scoped_refptr<BackgroundFetchRequestInfo>> pending_requests_; |
95 // unique_ptr, owned by the BackgroundFetchJobController. Right now we | 100 std::vector<scoped_refptr<BackgroundFetchRequestInfo>> active_requests_; |
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 | 101 |
100 // TODO(peter): Right now it's safe for this to be a vector because we only | 102 // 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. | 103 // allow a single parallel request. That stops when we start allowing more. |
102 static_assert(kMaximumBackgroundFetchParallelRequests == 1, | 104 static_assert(kMaximumBackgroundFetchParallelRequests == 1, |
103 "RegistrationData::completed_requests_ assumes no parallelism"); | 105 "RegistrationData::completed_requests_ assumes no parallelism"); |
104 | 106 |
105 std::vector<BackgroundFetchRequestInfo> completed_requests_; | 107 std::vector<scoped_refptr<BackgroundFetchRequestInfo>> completed_requests_; |
106 | 108 |
107 DISALLOW_COPY_AND_ASSIGN(RegistrationData); | 109 DISALLOW_COPY_AND_ASSIGN(RegistrationData); |
108 }; | 110 }; |
109 | 111 |
110 BackgroundFetchDataManager::BackgroundFetchDataManager( | 112 BackgroundFetchDataManager::BackgroundFetchDataManager( |
111 BrowserContext* browser_context) | 113 BrowserContext* browser_context) |
112 : weak_ptr_factory_(this) { | 114 : weak_ptr_factory_(this) { |
113 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 115 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
114 DCHECK(browser_context); | 116 DCHECK(browser_context); |
115 | 117 |
116 // Store the blob storage context for the given |browser_context|. | 118 // Store the blob storage context for the given |browser_context|. |
117 blob_storage_context_ = | 119 blob_storage_context_ = |
118 make_scoped_refptr(ChromeBlobStorageContext::GetFor(browser_context)); | 120 make_scoped_refptr(ChromeBlobStorageContext::GetFor(browser_context)); |
119 DCHECK(blob_storage_context_); | 121 DCHECK(blob_storage_context_); |
120 } | 122 } |
121 | 123 |
122 BackgroundFetchDataManager::~BackgroundFetchDataManager() = default; | 124 BackgroundFetchDataManager::~BackgroundFetchDataManager() = default; |
123 | 125 |
124 void BackgroundFetchDataManager::CreateRegistration( | 126 void BackgroundFetchDataManager::CreateRegistration( |
125 const BackgroundFetchRegistrationId& registration_id, | 127 const BackgroundFetchRegistrationId& registration_id, |
126 const std::vector<ServiceWorkerFetchRequest>& requests, | 128 const std::vector<ServiceWorkerFetchRequest>& requests, |
127 const BackgroundFetchOptions& options, | 129 const BackgroundFetchOptions& options, |
128 CreateRegistrationCallback callback) { | 130 CreateRegistrationCallback callback) { |
129 if (registrations_.find(registration_id) != registrations_.end()) { | 131 if (registrations_.find(registration_id) != registrations_.end()) { |
130 std::move(callback).Run(blink::mojom::BackgroundFetchError::DUPLICATED_TAG, | 132 std::move(callback).Run( |
131 std::vector<BackgroundFetchRequestInfo>()); | 133 blink::mojom::BackgroundFetchError::DUPLICATED_TAG, |
| 134 std::vector<scoped_refptr<BackgroundFetchRequestInfo>>()); |
132 return; | 135 return; |
133 } | 136 } |
134 | 137 |
135 std::unique_ptr<RegistrationData> registration_data = | 138 std::unique_ptr<RegistrationData> registration_data = |
136 base::MakeUnique<RegistrationData>(requests, options); | 139 base::MakeUnique<RegistrationData>(requests, options); |
137 | 140 |
138 // Create a vector with the initial requests to feed the Job Controller with. | 141 // Create a vector with the initial requests to feed the Job Controller with. |
139 std::vector<BackgroundFetchRequestInfo> initial_requests; | 142 std::vector<scoped_refptr<BackgroundFetchRequestInfo>> initial_requests; |
140 for (size_t i = 0; i < kMaximumBackgroundFetchParallelRequests; ++i) { | 143 for (size_t i = 0; i < kMaximumBackgroundFetchParallelRequests; ++i) { |
141 if (!registration_data->HasPendingRequests()) | 144 if (!registration_data->HasPendingRequests()) |
142 break; | 145 break; |
143 | 146 |
144 initial_requests.push_back(registration_data->GetPendingRequest()); | 147 initial_requests.push_back(registration_data->GetPendingRequest()); |
145 } | 148 } |
146 | 149 |
147 // Store the created |registration_data| so that we can easily access it. | 150 // Store the created |registration_data| so that we can easily access it. |
148 registrations_.insert( | 151 registrations_.insert( |
149 std::make_pair(registration_id, std::move(registration_data))); | 152 std::make_pair(registration_id, std::move(registration_data))); |
150 | 153 |
151 // Inform the |callback| of the newly created registration. | 154 // Inform the |callback| of the newly created registration. |
152 std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE, | 155 std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE, |
153 std::move(initial_requests)); | 156 std::move(initial_requests)); |
154 } | 157 } |
155 | 158 |
156 void BackgroundFetchDataManager::MarkRequestAsStarted( | 159 void BackgroundFetchDataManager::MarkRequestAsStarted( |
157 const BackgroundFetchRegistrationId& registration_id, | 160 const BackgroundFetchRegistrationId& registration_id, |
158 const BackgroundFetchRequestInfo& request, | 161 BackgroundFetchRequestInfo* request, |
159 const std::string& download_guid) { | 162 const std::string& download_guid) { |
160 auto iter = registrations_.find(registration_id); | 163 auto iter = registrations_.find(registration_id); |
161 DCHECK(iter != registrations_.end()); | 164 DCHECK(iter != registrations_.end()); |
162 | 165 |
163 RegistrationData* registration_data = iter->second.get(); | 166 RegistrationData* registration_data = iter->second.get(); |
164 registration_data->MarkRequestAsStarted(request, download_guid); | 167 registration_data->MarkRequestAsStarted(request, download_guid); |
165 } | 168 } |
166 | 169 |
167 void BackgroundFetchDataManager::MarkRequestAsCompleteAndGetNextRequest( | 170 void BackgroundFetchDataManager::MarkRequestAsCompleteAndGetNextRequest( |
168 const BackgroundFetchRegistrationId& registration_id, | 171 const BackgroundFetchRegistrationId& registration_id, |
169 const BackgroundFetchRequestInfo& request, | 172 BackgroundFetchRequestInfo* request, |
170 NextRequestCallback callback) { | 173 NextRequestCallback callback) { |
171 auto iter = registrations_.find(registration_id); | 174 auto iter = registrations_.find(registration_id); |
172 DCHECK(iter != registrations_.end()); | 175 DCHECK(iter != registrations_.end()); |
173 | 176 |
174 RegistrationData* registration_data = iter->second.get(); | 177 RegistrationData* registration_data = iter->second.get(); |
175 registration_data->MarkRequestAsComplete(request); | 178 registration_data->MarkRequestAsComplete(request); |
176 | 179 |
177 base::Optional<BackgroundFetchRequestInfo> next_request; | 180 scoped_refptr<BackgroundFetchRequestInfo> next_request; |
178 if (registration_data->HasPendingRequests()) | 181 if (registration_data->HasPendingRequests()) |
179 next_request = registration_data->GetPendingRequest(); | 182 next_request = registration_data->GetPendingRequest(); |
180 | 183 |
181 std::move(callback).Run(next_request); | 184 std::move(callback).Run(std::move(next_request)); |
182 } | 185 } |
183 | 186 |
184 void BackgroundFetchDataManager::GetSettledFetchesForRegistration( | 187 void BackgroundFetchDataManager::GetSettledFetchesForRegistration( |
185 const BackgroundFetchRegistrationId& registration_id, | 188 const BackgroundFetchRegistrationId& registration_id, |
186 SettledFetchesCallback callback) { | 189 SettledFetchesCallback callback) { |
187 auto iter = registrations_.find(registration_id); | 190 auto iter = registrations_.find(registration_id); |
188 DCHECK(iter != registrations_.end()); | 191 DCHECK(iter != registrations_.end()); |
189 | 192 |
190 RegistrationData* registration_data = iter->second.get(); | 193 RegistrationData* registration_data = iter->second.get(); |
191 DCHECK(!registration_data->HasPendingRequests()); | 194 DCHECK(!registration_data->HasPendingRequests()); |
192 | 195 |
193 const std::vector<BackgroundFetchRequestInfo>& requests = | 196 const std::vector<scoped_refptr<BackgroundFetchRequestInfo>>& requests = |
194 registration_data->GetCompletedRequests(); | 197 registration_data->GetCompletedRequests(); |
195 | 198 |
196 std::vector<BackgroundFetchSettledFetch> settled_fetches; | 199 std::vector<BackgroundFetchSettledFetch> settled_fetches; |
197 settled_fetches.reserve(requests.size()); | 200 settled_fetches.reserve(requests.size()); |
198 | 201 |
199 std::vector<std::unique_ptr<BlobHandle>> blob_handles; | 202 std::vector<std::unique_ptr<BlobHandle>> blob_handles; |
200 | 203 |
201 for (const auto& request : requests) { | 204 for (const auto& request : requests) { |
202 BackgroundFetchSettledFetch settled_fetch; | 205 BackgroundFetchSettledFetch settled_fetch; |
203 settled_fetch.request = request.fetch_request(); | 206 settled_fetch.request = request->fetch_request(); |
204 | 207 |
205 settled_fetch.response.url_list.push_back(request.GetURL()); | 208 settled_fetch.response.url_list.push_back(request->GetURL()); |
206 // TODO: settled_fetch.response.status_code | 209 // TODO: settled_fetch.response.status_code |
207 // TODO: settled_fetch.response.status_text | 210 // TODO: settled_fetch.response.status_text |
208 // TODO: settled_fetch.response.response_type | 211 // TODO: settled_fetch.response.response_type |
209 // TODO: settled_fetch.response.headers | 212 // TODO: settled_fetch.response.headers |
210 | 213 |
211 if (request.received_bytes() > 0) { | 214 if (request->received_bytes() > 0) { |
212 DCHECK(!request.file_path().empty()); | 215 DCHECK(!request->file_path().empty()); |
213 | 216 |
214 std::unique_ptr<BlobHandle> blob_handle = | 217 std::unique_ptr<BlobHandle> blob_handle = |
215 blob_storage_context_->CreateFileBackedBlob( | 218 blob_storage_context_->CreateFileBackedBlob( |
216 request.file_path(), 0 /* offset */, request.received_bytes(), | 219 request->file_path(), 0 /* offset */, request->received_bytes(), |
217 base::Time() /* expected_modification_time */); | 220 base::Time() /* expected_modification_time */); |
218 | 221 |
219 // TODO(peter): Appropriately handle !blob_handle | 222 // TODO(peter): Appropriately handle !blob_handle |
220 if (blob_handle) { | 223 if (blob_handle) { |
221 settled_fetch.response.blob_uuid = blob_handle->GetUUID(); | 224 settled_fetch.response.blob_uuid = blob_handle->GetUUID(); |
222 settled_fetch.response.blob_size = request.received_bytes(); | 225 settled_fetch.response.blob_size = request->received_bytes(); |
223 | 226 |
224 blob_handles.push_back(std::move(blob_handle)); | 227 blob_handles.push_back(std::move(blob_handle)); |
225 } | 228 } |
226 } | 229 } |
227 | 230 |
228 // TODO: settled_fetch.response.error | 231 // TODO: settled_fetch.response.error |
229 // TODO: settled_fetch.response.response_time | 232 // TODO: settled_fetch.response.response_time |
230 // TODO: settled_fetch.response.cors_exposed_header_names | 233 // TODO: settled_fetch.response.cors_exposed_header_names |
231 | 234 |
232 settled_fetches.push_back(settled_fetch); | 235 settled_fetches.push_back(settled_fetch); |
(...skipping 11 matching lines...) Expand all Loading... |
244 std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_TAG); | 247 std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_TAG); |
245 return; | 248 return; |
246 } | 249 } |
247 | 250 |
248 registrations_.erase(iter); | 251 registrations_.erase(iter); |
249 | 252 |
250 std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE); | 253 std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE); |
251 } | 254 } |
252 | 255 |
253 } // namespace content | 256 } // namespace content |
OLD | NEW |