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 "base/memory/ptr_util.h" | 7 #include "base/memory/ptr_util.h" |
8 #include "content/browser/background_fetch/background_fetch_context.h" | 8 #include "content/browser/background_fetch/background_fetch_context.h" |
| 9 #include "content/browser/background_fetch/background_fetch_job_response_data.h" |
9 #include "content/browser/background_fetch/background_fetch_request_info.h" | 10 #include "content/browser/background_fetch/background_fetch_request_info.h" |
| 11 #include "content/public/browser/blob_handle.h" |
| 12 #include "content/public/browser/browser_context.h" |
| 13 #include "content/public/browser/download_interrupt_reasons.h" |
| 14 #include "content/public/browser/download_item.h" |
10 | 15 |
11 namespace content { | 16 namespace content { |
12 | 17 |
13 BackgroundFetchDataManager::BackgroundFetchDataManager( | 18 BackgroundFetchDataManager::BackgroundFetchDataManager( |
14 BackgroundFetchContext* background_fetch_context) | 19 BrowserContext* browser_context) |
15 : background_fetch_context_(background_fetch_context) { | 20 : browser_context_(browser_context), weak_ptr_factory_(this) { |
16 DCHECK(background_fetch_context_); | 21 DCHECK(browser_context_); |
17 // TODO(harkness) Read from persistent storage and recreate requests. | 22 // TODO(harkness) Read from persistent storage and recreate requests. |
18 } | 23 } |
19 | 24 |
20 BackgroundFetchDataManager::~BackgroundFetchDataManager() = default; | 25 BackgroundFetchDataManager::~BackgroundFetchDataManager() = default; |
21 | 26 |
22 std::unique_ptr<BackgroundFetchJobData> | 27 void BackgroundFetchDataManager::CreateRequest( |
23 BackgroundFetchDataManager::CreateRequest( | |
24 std::unique_ptr<BackgroundFetchJobInfo> job_info, | 28 std::unique_ptr<BackgroundFetchJobInfo> job_info, |
25 BackgroundFetchRequestInfos request_infos) { | 29 BackgroundFetchRequestInfos request_infos) { |
26 JobIdentifier id(job_info->service_worker_registration_id(), job_info->tag()); | 30 JobIdentifier id(job_info->service_worker_registration_id(), job_info->tag()); |
27 // Ensure that this is not a duplicate request. | 31 // Ensure that this is not a duplicate request. |
28 if (service_worker_tag_map_.find(id) != service_worker_tag_map_.end()) { | 32 if (service_worker_tag_map_.find(id) != service_worker_tag_map_.end()) { |
29 DVLOG(1) << "Origin " << job_info->origin() | 33 DVLOG(1) << "Origin " << job_info->origin() |
30 << " has already created a batch request with tag " | 34 << " has already created a batch request with tag " |
31 << job_info->tag(); | 35 << job_info->tag(); |
32 // TODO(harkness) Figure out how to return errors like this. | 36 // TODO(harkness) Figure out how to return errors like this. |
33 return nullptr; | 37 return; |
34 } | 38 } |
35 | 39 |
36 // Add the request to our maps and return a JobData to track the individual | 40 // Add the JobInfo to the in-memory map, and write the individual requests out |
37 // files in the request. | 41 // to storage. |
| 42 job_info->set_num_requests(request_infos.size()); |
38 const std::string job_guid = job_info->guid(); | 43 const std::string job_guid = job_info->guid(); |
39 service_worker_tag_map_[id] = job_guid; | 44 service_worker_tag_map_[id] = job_guid; |
40 WriteJobToStorage(std::move(job_info), std::move(request_infos)); | 45 WriteJobToStorage(std::move(job_info), std::move(request_infos)); |
41 // TODO(harkness): Remove data when the job is complete. | |
42 | |
43 return base::MakeUnique<BackgroundFetchJobData>( | |
44 ReadRequestsFromStorage(job_guid)); | |
45 } | 46 } |
46 | 47 |
47 void BackgroundFetchDataManager::WriteJobToStorage( | 48 void BackgroundFetchDataManager::WriteJobToStorage( |
48 std::unique_ptr<BackgroundFetchJobInfo> job_info, | 49 std::unique_ptr<BackgroundFetchJobInfo> job_info, |
49 BackgroundFetchRequestInfos request_infos) { | 50 BackgroundFetchRequestInfos request_infos) { |
50 // TODO(harkness): Replace these maps with actually writing to storage. | |
51 // TODO(harkness): Check for job_guid clash. | 51 // TODO(harkness): Check for job_guid clash. |
52 const std::string job_guid = job_info->guid(); | 52 const std::string job_guid = job_info->guid(); |
53 job_map_[job_guid] = std::move(job_info); | 53 job_map_[job_guid] = std::move(job_info); |
54 request_map_[job_guid] = std::move(request_infos); | 54 |
| 55 // Make an explicit copy of the original requests |
| 56 // TODO(harkness): Replace this with actually writing to storage. |
| 57 std::vector<BackgroundFetchRequestInfo> requests; |
| 58 for (const auto& request_info : request_infos) { |
| 59 requests.emplace_back(*(request_info.get())); |
| 60 } |
| 61 request_map_[job_guid] = std::move(requests); |
| 62 |
| 63 // |request_infos| will be destroyed when it leaves scope here. |
55 } | 64 } |
56 | 65 |
57 // TODO(harkness): This should be changed to read (and cache) small numbers of | 66 void BackgroundFetchDataManager::WriteRequestToStorage( |
58 // the RequestInfos instead of returning all of them. | 67 const std::string& job_guid, |
59 BackgroundFetchRequestInfos& | 68 BackgroundFetchRequestInfo* request_info) { |
60 BackgroundFetchDataManager::ReadRequestsFromStorage( | 69 std::vector<BackgroundFetchRequestInfo>& request_infos = |
| 70 request_map_[job_guid]; |
| 71 |
| 72 // Copy the updated |request_info| over the in-memory version. |
| 73 for (size_t i = 0; i < request_infos.size(); i++) { |
| 74 if (request_infos[i].guid() == request_info->guid()) |
| 75 request_infos[i] = *request_info; |
| 76 } |
| 77 } |
| 78 |
| 79 std::unique_ptr<BackgroundFetchRequestInfo> |
| 80 BackgroundFetchDataManager::GetRequestInfo(const std::string& job_guid, |
| 81 size_t request_index) { |
| 82 // Explicitly create a copy. When this is persisted to StorageWorkerStorage, |
| 83 // the request_map_ will not exist. |
| 84 auto iter = request_map_.find(job_guid); |
| 85 DCHECK(iter != request_map_.end()); |
| 86 const std::vector<BackgroundFetchRequestInfo>& request_infos = iter->second; |
| 87 |
| 88 DCHECK(request_index <= request_infos.size()); |
| 89 return base::MakeUnique<BackgroundFetchRequestInfo>( |
| 90 request_infos[request_index]); |
| 91 } |
| 92 |
| 93 void BackgroundFetchDataManager::GetJobResponse( |
| 94 const std::string& job_guid, |
| 95 const BackgroundFetchResponseCompleteCallback& callback) { |
| 96 BackgroundFetchJobInfo* job_info = job_map_[job_guid].get(); |
| 97 DCHECK(job_info); |
| 98 |
| 99 // Create a BackgroundFetchJobResponseData object which will aggregate |
| 100 // together the response blobs. |
| 101 job_info->set_job_response_data( |
| 102 base::MakeUnique<BackgroundFetchJobResponseData>(job_info->num_requests(), |
| 103 callback)); |
| 104 |
| 105 // Iterate over the requests and create blobs for each response. |
| 106 for (size_t request_index = 0; request_index < job_info->num_requests(); |
| 107 request_index++) { |
| 108 // TODO(harkness): This will need to be asynchronous. |
| 109 std::unique_ptr<BackgroundFetchRequestInfo> request_info = |
| 110 GetRequestInfo(job_guid, request_index); |
| 111 |
| 112 // TODO(harkness): Only create a blob response if the request was |
| 113 // successful. Otherwise create an error response. |
| 114 content::BrowserContext::CreateFileBackedBlob( |
| 115 browser_context_, request_info->file_path(), 0 /* offset */, |
| 116 request_info->received_bytes(), |
| 117 base::Time() /* expected_modification_time */, |
| 118 base::Bind(&BackgroundFetchDataManager::DidGetRequestResponse, |
| 119 weak_ptr_factory_.GetWeakPtr(), job_guid, request_index)); |
| 120 } |
| 121 } |
| 122 |
| 123 void BackgroundFetchDataManager::DidGetRequestResponse( |
| 124 const std::string& job_guid, |
| 125 int request_sequence_number, |
| 126 std::unique_ptr<BlobHandle> blob_handle) { |
| 127 BackgroundFetchJobInfo* job_info = job_map_[job_guid].get(); |
| 128 DCHECK(job_info); |
| 129 |
| 130 BackgroundFetchJobResponseData* job_response_data = |
| 131 job_info->job_response_data(); |
| 132 DCHECK(job_response_data); |
| 133 |
| 134 job_response_data->AddResponse(request_sequence_number, |
| 135 std::move(blob_handle)); |
| 136 } |
| 137 |
| 138 bool BackgroundFetchDataManager::UpdateRequestState( |
| 139 const std::string& job_guid, |
| 140 const std::string& request_guid, |
| 141 DownloadItem::DownloadState state, |
| 142 DownloadInterruptReason interrupt_reason) { |
| 143 // Find the request and set the state and the interrupt reason. |
| 144 BackgroundFetchJobInfo* job_info = job_map_[job_guid].get(); |
| 145 DCHECK(job_info); |
| 146 BackgroundFetchRequestInfo* request = |
| 147 job_info->GetActiveRequest(request_guid); |
| 148 DCHECK(request); |
| 149 request->set_state(state); |
| 150 request->set_interrupt_reason(interrupt_reason); |
| 151 |
| 152 // If the request is now finished, remove it from the active requests. |
| 153 switch (state) { |
| 154 case DownloadItem::DownloadState::COMPLETE: |
| 155 case DownloadItem::DownloadState::CANCELLED: |
| 156 WriteRequestToStorage(job_guid, request); |
| 157 job_info->RemoveActiveRequest(request_guid); |
| 158 break; |
| 159 case DownloadItem::DownloadState::IN_PROGRESS: |
| 160 case DownloadItem::DownloadState::INTERRUPTED: |
| 161 case DownloadItem::DownloadState::MAX_DOWNLOAD_STATE: |
| 162 break; |
| 163 } |
| 164 |
| 165 // Return a boolean indicating whether there are more requests to be |
| 166 // processed. |
| 167 return job_info->HasRequestsRemaining(); |
| 168 } |
| 169 |
| 170 void BackgroundFetchDataManager::UpdateRequestStorageState( |
| 171 const std::string& job_guid, |
| 172 const std::string& request_guid, |
| 173 const base::FilePath& file_path, |
| 174 int64_t received_bytes) { |
| 175 BackgroundFetchJobInfo* job_info = job_map_[job_guid].get(); |
| 176 DCHECK(job_info); |
| 177 BackgroundFetchRequestInfo* request = |
| 178 job_info->GetActiveRequest(request_guid); |
| 179 DCHECK(request); |
| 180 request->set_file_path(file_path); |
| 181 request->set_received_bytes(received_bytes); |
| 182 } |
| 183 |
| 184 const BackgroundFetchRequestInfo& |
| 185 BackgroundFetchDataManager::GetNextBackgroundFetchRequestInfo( |
61 const std::string& job_guid) { | 186 const std::string& job_guid) { |
62 return request_map_[job_guid]; | 187 BackgroundFetchJobInfo* job_info = job_map_[job_guid].get(); |
| 188 DCHECK(job_info); |
| 189 |
| 190 // TODO(harkness): This needs to be async when it queries real storage. |
| 191 std::unique_ptr<BackgroundFetchRequestInfo> request_info = |
| 192 GetRequestInfo(job_guid, job_info->next_request_index()); |
| 193 const std::string request_guid = request_info->guid(); |
| 194 job_info->AddActiveRequest(std::move(request_info)); |
| 195 return *job_info->GetActiveRequest(request_guid); |
| 196 } |
| 197 |
| 198 bool BackgroundFetchDataManager::IsComplete(const std::string& job_guid) const { |
| 199 auto iter = job_map_.find(job_guid); |
| 200 DCHECK(iter != job_map_.end()); |
| 201 return iter->second->IsComplete(); |
| 202 } |
| 203 |
| 204 bool BackgroundFetchDataManager::HasRequestsRemaining( |
| 205 const std::string& job_guid) const { |
| 206 auto iter = job_map_.find(job_guid); |
| 207 DCHECK(iter != job_map_.end()); |
| 208 return iter->second->HasRequestsRemaining(); |
| 209 } |
| 210 |
| 211 void BackgroundFetchDataManager::UpdateRequestDownloadGuid( |
| 212 const std::string& job_guid, |
| 213 const std::string& request_guid, |
| 214 const std::string& download_guid) { |
| 215 BackgroundFetchJobInfo* job_info = job_map_[job_guid].get(); |
| 216 DCHECK(job_info); |
| 217 BackgroundFetchRequestInfo* request = |
| 218 job_info->GetActiveRequest(request_guid); |
| 219 DCHECK(request); |
| 220 request->set_download_guid(download_guid); |
63 } | 221 } |
64 | 222 |
65 } // namespace content | 223 } // namespace content |
OLD | NEW |