OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "shell/application_manager/network_fetcher.h" | 5 #include "shell/application_manager/network_fetcher.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/files/file.h" | 9 #include "base/files/file.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
(...skipping 18 matching lines...) Expand all Loading... |
29 #if defined(OS_LINUX) | 29 #if defined(OS_LINUX) |
30 char kArchitecture[] = "linux-x64"; | 30 char kArchitecture[] = "linux-x64"; |
31 #elif defined(OS_ANDROID) | 31 #elif defined(OS_ANDROID) |
32 char kArchitecture[] = "android-arm"; | 32 char kArchitecture[] = "android-arm"; |
33 #elif defined(OS_MACOSX) | 33 #elif defined(OS_MACOSX) |
34 char kArchitecture[] = "macosx"; | 34 char kArchitecture[] = "macosx"; |
35 #else | 35 #else |
36 #error "Unsupported." | 36 #error "Unsupported." |
37 #endif | 37 #endif |
38 | 38 |
| 39 const bool kScheduleUpdate = true; |
| 40 const bool kDoNotScheduleUpdate = false; |
| 41 |
39 // The delay to wait before trying to update an application after having served | 42 // The delay to wait before trying to update an application after having served |
40 // it from the cache. | 43 // it from the cache. |
41 const uint32_t kUpdateApplicationDelayInSeconds = 60; | 44 const uint32_t kUpdateApplicationDelayInSeconds = 60; |
42 | 45 |
43 base::FilePath ToFilePath(const mojo::Array<uint8_t>& array) { | 46 base::FilePath ToFilePath(const mojo::Array<uint8_t>& array) { |
44 return base::FilePath( | 47 return base::FilePath( |
45 std::string(reinterpret_cast<const char*>(&array.front()), array.size())); | 48 std::string(reinterpret_cast<const char*>(&array.front()), array.size())); |
46 } | 49 } |
47 | 50 |
48 void IgnoreResult(bool result) {} | 51 void IgnoreResult(bool result) {} |
49 | 52 |
50 mojo::URLRequestPtr GetRequest(const GURL& url, bool disable_cache) { | 53 mojo::URLRequestPtr GetRequest(const GURL& url, bool disable_cache) { |
51 mojo::URLRequestPtr request(mojo::URLRequest::New()); | 54 mojo::URLRequestPtr request(mojo::URLRequest::New()); |
52 request->url = mojo::String::From(url); | 55 request->url = mojo::String::From(url); |
53 request->auto_follow_redirects = false; | 56 request->auto_follow_redirects = false; |
54 if (disable_cache) | 57 if (disable_cache) |
55 request->cache_mode = mojo::URLRequest::CACHE_MODE_BYPASS_CACHE; | 58 request->cache_mode = mojo::URLRequest::CACHE_MODE_BYPASS_CACHE; |
56 auto architecture_header = mojo::HttpHeader::New(); | 59 auto architecture_header = mojo::HttpHeader::New(); |
57 architecture_header->name = "X-Architecture"; | 60 architecture_header->name = "X-Architecture"; |
58 architecture_header->value = kArchitecture; | 61 architecture_header->value = kArchitecture; |
59 mojo::Array<mojo::HttpHeaderPtr> headers; | 62 mojo::Array<mojo::HttpHeaderPtr> headers; |
60 headers.push_back(architecture_header.Pass()); | 63 headers.push_back(architecture_header.Pass()); |
61 request->headers = headers.Pass(); | 64 request->headers = headers.Pass(); |
62 | 65 |
63 return request.Pass(); | 66 return request.Pass(); |
64 } | 67 } |
65 | 68 |
| 69 // Clone an URLResponse, except for the body. |
| 70 mojo::URLResponsePtr CloneResponse(const mojo::URLResponsePtr& response) { |
| 71 mojo::URLResponsePtr cloned = mojo::URLResponse::New(); |
| 72 cloned->error = response->error.Clone(); |
| 73 cloned->url = response->url; |
| 74 cloned->status_code = response->status_code; |
| 75 cloned->status_line = response->status_line; |
| 76 cloned->headers = response->headers.Clone(); |
| 77 cloned->mime_type = response->mime_type; |
| 78 cloned->charset = response->charset; |
| 79 cloned->redirect_method = response->redirect_method; |
| 80 cloned->redirect_url = response->redirect_url; |
| 81 cloned->redirect_referrer = response->redirect_referrer; |
| 82 return cloned.Pass(); |
| 83 } |
| 84 |
66 // This class is self owned and will delete itself after having tried to update | 85 // This class is self owned and will delete itself after having tried to update |
67 // the application cache. | 86 // the application cache. |
68 class ApplicationUpdater : public base::MessageLoop::DestructionObserver { | 87 class ApplicationUpdater : public base::MessageLoop::DestructionObserver { |
69 public: | 88 public: |
70 ApplicationUpdater(const GURL& url, | 89 ApplicationUpdater(const GURL& url, |
71 const base::TimeDelta& update_delay, | 90 const base::TimeDelta& update_delay, |
72 mojo::URLResponseDiskCache* url_response_disk_cache, | 91 mojo::URLResponseDiskCache* url_response_disk_cache, |
73 mojo::NetworkService* network_service); | 92 mojo::NetworkService* network_service); |
74 ~ApplicationUpdater() override; | 93 ~ApplicationUpdater() override; |
75 | 94 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 } | 131 } |
113 | 132 |
114 void ApplicationUpdater::UpdateApplication() { | 133 void ApplicationUpdater::UpdateApplication() { |
115 network_service_->CreateURLLoader(GetProxy(&url_loader_)); | 134 network_service_->CreateURLLoader(GetProxy(&url_loader_)); |
116 url_loader_->Start( | 135 url_loader_->Start( |
117 GetRequest(url_, false), | 136 GetRequest(url_, false), |
118 base::Bind(&ApplicationUpdater::OnLoadComplete, base::Unretained(this))); | 137 base::Bind(&ApplicationUpdater::OnLoadComplete, base::Unretained(this))); |
119 } | 138 } |
120 | 139 |
121 void ApplicationUpdater::OnLoadComplete(mojo::URLResponsePtr response) { | 140 void ApplicationUpdater::OnLoadComplete(mojo::URLResponsePtr response) { |
| 141 std::string url = response->url; |
122 url_response_disk_cache_->Update(response.Pass()); | 142 url_response_disk_cache_->Update(response.Pass()); |
| 143 url_response_disk_cache_->Validate(url); |
123 delete this; | 144 delete this; |
124 } | 145 } |
125 | 146 |
126 } // namespace | 147 } // namespace |
127 | 148 |
128 NetworkFetcher::NetworkFetcher( | 149 NetworkFetcher::NetworkFetcher( |
129 bool disable_cache, | 150 bool disable_cache, |
130 bool force_offline_by_default, | 151 bool force_offline_by_default, |
131 const GURL& url, | 152 const GURL& url, |
132 mojo::URLResponseDiskCache* url_response_disk_cache, | 153 mojo::URLResponseDiskCache* url_response_disk_cache, |
133 mojo::NetworkService* network_service, | 154 mojo::NetworkService* network_service, |
134 const FetchCallback& loader_callback) | 155 const FetchCallback& loader_callback) |
135 : Fetcher(loader_callback), | 156 : Fetcher(loader_callback), |
136 disable_cache_(disable_cache), | 157 disable_cache_(disable_cache), |
137 force_offline_by_default_(force_offline_by_default), | 158 force_offline_by_default_(force_offline_by_default), |
138 url_(url), | 159 url_(url), |
139 url_response_disk_cache_(url_response_disk_cache), | 160 url_response_disk_cache_(url_response_disk_cache), |
140 network_service_(network_service), | 161 network_service_(network_service), |
141 weak_ptr_factory_(this) { | 162 weak_ptr_factory_(this) { |
142 if (CanLoadDirectlyFromCache()) { | 163 if (CanLoadDirectlyFromCache()) { |
143 LoadFromCache(true); | 164 LoadFromCache(); |
144 } else { | 165 } else { |
145 StartNetworkRequest(); | 166 StartNetworkRequest(); |
146 } | 167 } |
147 } | 168 } |
148 | 169 |
149 NetworkFetcher::~NetworkFetcher() { | 170 NetworkFetcher::~NetworkFetcher() { |
150 } | 171 } |
151 | 172 |
152 const GURL& NetworkFetcher::GetURL() const { | 173 const GURL& NetworkFetcher::GetURL() const { |
153 return url_; | 174 return url_; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 if (disable_cache_) | 224 if (disable_cache_) |
204 return false; | 225 return false; |
205 | 226 |
206 if (force_offline_by_default_) | 227 if (force_offline_by_default_) |
207 return true; | 228 return true; |
208 | 229 |
209 const std::string& host = url_.host(); | 230 const std::string& host = url_.host(); |
210 return !(host == "localhost" || host == "127.0.0.1" || host == "[::1]"); | 231 return !(host == "localhost" || host == "127.0.0.1" || host == "[::1]"); |
211 } | 232 } |
212 | 233 |
213 void NetworkFetcher::LoadFromCache(bool schedule_update) { | 234 void NetworkFetcher::LoadFromCache() { |
214 url_response_disk_cache_->Get( | 235 url_response_disk_cache_->Get( |
215 mojo::String::From(url_), | 236 mojo::String::From(url_), |
216 base::Bind(&NetworkFetcher::OnCachedResponseReceived, | 237 base::Bind(&NetworkFetcher::OnResponseReceived, base::Unretained(this), |
217 base::Unretained(this), schedule_update)); | 238 kScheduleUpdate)); |
218 } | 239 } |
219 | 240 |
220 void NetworkFetcher::OnCachedResponseReceived( | 241 void NetworkFetcher::OnResponseReceived(bool schedule_update, |
221 bool schedule_update, | 242 mojo::URLResponsePtr response, |
222 mojo::URLResponsePtr response, | 243 mojo::Array<uint8_t> path_as_array, |
223 mojo::Array<uint8_t> path_as_array, | 244 mojo::Array<uint8_t> cache_dir) { |
224 mojo::Array<uint8_t> cache_dir) { | |
225 if (!response) { | 245 if (!response) { |
226 // Not in cache, loading from net. | 246 // Not in cache, loading from net. |
227 StartNetworkRequest(); | 247 StartNetworkRequest(); |
228 return; | 248 return; |
229 } | 249 } |
230 if (schedule_update) { | 250 if (schedule_update) { |
231 // The response has been found in the cache. Plan updating the application. | 251 // The response has been found in the cache. Plan updating the application. |
232 new ApplicationUpdater( | 252 new ApplicationUpdater( |
233 url_, base::TimeDelta::FromSeconds(kUpdateApplicationDelayInSeconds), | 253 url_, base::TimeDelta::FromSeconds(kUpdateApplicationDelayInSeconds), |
234 url_response_disk_cache_, network_service_); | 254 url_response_disk_cache_, network_service_); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 delete this; | 287 delete this; |
268 return; | 288 return; |
269 } | 289 } |
270 | 290 |
271 if (!response->redirect_url.is_null()) { | 291 if (!response->redirect_url.is_null()) { |
272 response_ = response.Pass(); | 292 response_ = response.Pass(); |
273 loader_callback_.Run(make_scoped_ptr(this)); | 293 loader_callback_.Run(make_scoped_ptr(this)); |
274 return; | 294 return; |
275 } | 295 } |
276 | 296 |
| 297 mojo::URLResponsePtr cloned_response = CloneResponse(response); |
277 url_response_disk_cache_->UpdateAndGet( | 298 url_response_disk_cache_->UpdateAndGet( |
278 response.Pass(), base::Bind(&NetworkFetcher::OnFileSavedToCache, | 299 response.Pass(), base::Bind(&NetworkFetcher::OnFileSavedToCache, |
279 weak_ptr_factory_.GetWeakPtr())); | 300 weak_ptr_factory_.GetWeakPtr(), |
| 301 base::Passed(cloned_response.Pass()))); |
280 } | 302 } |
281 | 303 |
282 void NetworkFetcher::OnFileSavedToCache(mojo::Array<uint8_t> path_as_array, | 304 void NetworkFetcher::OnFileSavedToCache(mojo::URLResponsePtr response, |
| 305 mojo::Array<uint8_t> path_as_array, |
283 mojo::Array<uint8_t> cache_dir) { | 306 mojo::Array<uint8_t> cache_dir) { |
284 if (!path_as_array) { | 307 if (!path_as_array) { |
285 LOG(WARNING) << "Error when retrieving content from cache for: " | 308 LOG(WARNING) << "Error when retrieving content from cache for: " |
286 << url_.spec(); | 309 << url_.spec(); |
287 loader_callback_.Run(nullptr); | 310 loader_callback_.Run(nullptr); |
288 delete this; | 311 delete this; |
289 return; | 312 return; |
290 } | 313 } |
291 LoadFromCache(false); | 314 OnResponseReceived(kDoNotScheduleUpdate, response.Pass(), |
| 315 path_as_array.Pass(), cache_dir.Pass()); |
292 } | 316 } |
293 | 317 |
294 void NetworkFetcher::RecordCacheToURLMapping(const base::FilePath& path, | 318 void NetworkFetcher::RecordCacheToURLMapping(const base::FilePath& path, |
295 const GURL& url) { | 319 const GURL& url) { |
296 // This is used to extract symbols on android. | 320 // This is used to extract symbols on android. |
297 // TODO(eseidel): All users of this log should move to using the map file. | 321 // TODO(eseidel): All users of this log should move to using the map file. |
298 LOG(INFO) << "Caching mojo app " << url << " at " << path.value(); | 322 LOG(INFO) << "Caching mojo app " << url << " at " << path.value(); |
299 | 323 |
300 base::FilePath temp_dir; | 324 base::FilePath temp_dir; |
301 base::GetTempDir(&temp_dir); | 325 base::GetTempDir(&temp_dir); |
302 base::ProcessId pid = base::Process::Current().Pid(); | 326 base::ProcessId pid = base::Process::Current().Pid(); |
303 std::string map_name = base::StringPrintf("mojo_shell.%d.maps", pid); | 327 std::string map_name = base::StringPrintf("mojo_shell.%d.maps", pid); |
304 base::FilePath map_path = temp_dir.Append(map_name); | 328 base::FilePath map_path = temp_dir.Append(map_name); |
305 | 329 |
306 // TODO(eseidel): Paths or URLs with spaces will need quoting. | 330 // TODO(eseidel): Paths or URLs with spaces will need quoting. |
307 std::string map_entry = | 331 std::string map_entry = |
308 base::StringPrintf("%s %s\n", path.value().c_str(), url.spec().c_str()); | 332 base::StringPrintf("%s %s\n", path.value().c_str(), url.spec().c_str()); |
309 // TODO(eseidel): AppendToFile is missing O_CREAT, crbug.com/450696 | 333 // TODO(eseidel): AppendToFile is missing O_CREAT, crbug.com/450696 |
310 if (!PathExists(map_path)) { | 334 if (!PathExists(map_path)) { |
311 base::WriteFile(map_path, map_entry.data(), map_entry.length()); | 335 base::WriteFile(map_path, map_entry.data(), map_entry.length()); |
312 } else { | 336 } else { |
313 base::AppendToFile(map_path, map_entry.data(), map_entry.length()); | 337 base::AppendToFile(map_path, map_entry.data(), map_entry.length()); |
314 } | 338 } |
315 } | 339 } |
316 | 340 |
317 } // namespace shell | 341 } // namespace shell |
OLD | NEW |