| 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 |