| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "chrome/browser/android/webapk/webapk_installer.h" | 5 #include "chrome/browser/android/webapk/webapk_installer.h" |
| 6 | 6 |
| 7 #include "base/android/build_info.h" | 7 #include "base/android/build_info.h" |
| 8 #include "base/android/jni_android.h" | 8 #include "base/android/jni_android.h" |
| 9 #include "base/android/jni_string.h" | 9 #include "base/android/jni_string.h" |
| 10 #include "base/android/path_utils.h" | 10 #include "base/android/path_utils.h" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 "https://webapk.googleapis.com/v1/webApks/" | 45 "https://webapk.googleapis.com/v1/webApks/" |
| 46 "?alt=proto&key=AIzaSyAoI6v-F31-3t9NunLYEiKcPIqgTJIUZBw"; | 46 "?alt=proto&key=AIzaSyAoI6v-F31-3t9NunLYEiKcPIqgTJIUZBw"; |
| 47 | 47 |
| 48 // The MIME type of the POST data sent to the server. | 48 // The MIME type of the POST data sent to the server. |
| 49 const char kProtoMimeType[] = "application/x-protobuf"; | 49 const char kProtoMimeType[] = "application/x-protobuf"; |
| 50 | 50 |
| 51 // The default number of milliseconds to wait for the WebAPK download URL from | 51 // The default number of milliseconds to wait for the WebAPK download URL from |
| 52 // the WebAPK server. | 52 // the WebAPK server. |
| 53 const int kWebApkDownloadUrlTimeoutMs = 60000; | 53 const int kWebApkDownloadUrlTimeoutMs = 60000; |
| 54 | 54 |
| 55 // The default number of milliseconds to wait for the WebAPK download to | |
| 56 // complete. | |
| 57 const int kDownloadTimeoutMs = 60000; | |
| 58 | |
| 59 const int kWorldReadableFilePermission = base::FILE_PERMISSION_READ_BY_USER | | |
| 60 base::FILE_PERMISSION_READ_BY_GROUP | | |
| 61 base::FILE_PERMISSION_READ_BY_OTHERS; | |
| 62 const int kDefaultWebApkVersion = 1; | |
| 63 | |
| 64 // Returns the WebAPK server URL based on the command line. | 55 // Returns the WebAPK server URL based on the command line. |
| 65 GURL GetServerUrl() { | 56 GURL GetServerUrl() { |
| 66 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 57 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| 67 GURL command_line_url( | 58 GURL command_line_url( |
| 68 command_line->GetSwitchValueASCII(switches::kWebApkServerUrl)); | 59 command_line->GetSwitchValueASCII(switches::kWebApkServerUrl)); |
| 69 return command_line_url.is_valid() ? command_line_url | 60 return command_line_url.is_valid() ? command_line_url |
| 70 : GURL(kDefaultServerUrl); | 61 : GURL(kDefaultServerUrl); |
| 71 } | 62 } |
| 72 | 63 |
| 73 // Returns the scope from |info| if it is specified. Otherwise, returns the | 64 // Returns the scope from |info| if it is specified. Otherwise, returns the |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 callback.Run(std::move(webapk)); | 159 callback.Run(std::move(webapk)); |
| 169 } | 160 } |
| 170 | 161 |
| 171 // Returns task runner for running background tasks. | 162 // Returns task runner for running background tasks. |
| 172 scoped_refptr<base::TaskRunner> GetBackgroundTaskRunner() { | 163 scoped_refptr<base::TaskRunner> GetBackgroundTaskRunner() { |
| 173 return content::BrowserThread::GetBlockingPool() | 164 return content::BrowserThread::GetBlockingPool() |
| 174 ->GetTaskRunnerWithShutdownBehavior( | 165 ->GetTaskRunnerWithShutdownBehavior( |
| 175 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); | 166 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); |
| 176 } | 167 } |
| 177 | 168 |
| 178 // Creates a directory depending on the type of the task, and set permissions. | |
| 179 // It also creates any parent directory along the path if doesn't exist, | |
| 180 // and sets permissions as well. | |
| 181 // The previously downloaded APKs are deleted in order to clean up unused cached | |
| 182 // data. | |
| 183 base::FilePath CreateSubDirAndSetPermissionsInBackground( | |
| 184 const base::StringPiece& output_dir_name, | |
| 185 const std::string& package_name) { | |
| 186 base::FilePath output_root_dir; | |
| 187 base::android::GetCacheDirectory(&output_root_dir); | |
| 188 base::FilePath webapk_dir = output_root_dir.AppendASCII("webapks"); | |
| 189 // Creating different downloaded directory for install/update cases is | |
| 190 // to prevent deleting the APK which is still in use when an install and an | |
| 191 // update happen at the same time. However, it doesn't help the cases of when | |
| 192 // mutiple installs (or multiple updates) happen at the same time. | |
| 193 base::FilePath output_dir = webapk_dir.AppendASCII(output_dir_name); | |
| 194 int posix_permissions = kWorldReadableFilePermission | | |
| 195 base::FILE_PERMISSION_WRITE_BY_USER | | |
| 196 base::FILE_PERMISSION_EXECUTE_BY_USER | | |
| 197 base::FILE_PERMISSION_EXECUTE_BY_OTHERS; | |
| 198 if (base::PathExists(output_dir)) | |
| 199 base::DeleteFile(output_dir, true); | |
| 200 | |
| 201 // Creates the directory to download and sets permissions. | |
| 202 if (!base::CreateDirectory(output_dir) || | |
| 203 !base::SetPosixFilePermissions(webapk_dir, posix_permissions) || | |
| 204 !base::SetPosixFilePermissions(output_dir, posix_permissions)) | |
| 205 return base::FilePath(); | |
| 206 | |
| 207 return output_dir; | |
| 208 } | |
| 209 | |
| 210 } // anonymous namespace | 169 } // anonymous namespace |
| 211 | 170 |
| 212 WebApkInstaller::~WebApkInstaller() { | 171 WebApkInstaller::~WebApkInstaller() { |
| 213 JNIEnv* env = base::android::AttachCurrentThread(); | 172 JNIEnv* env = base::android::AttachCurrentThread(); |
| 214 Java_WebApkInstaller_destroy(env, java_ref_); | 173 Java_WebApkInstaller_destroy(env, java_ref_); |
| 215 java_ref_.Reset(); | 174 java_ref_.Reset(); |
| 216 } | 175 } |
| 217 | 176 |
| 218 // static | 177 // static |
| 219 void WebApkInstaller::InstallAsync(content::BrowserContext* context, | 178 void WebApkInstaller::InstallAsync(content::BrowserContext* context, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 int webapk_version, | 217 int webapk_version, |
| 259 const std::map<std::string, std::string>& icon_url_to_murmur2_hash, | 218 const std::map<std::string, std::string>& icon_url_to_murmur2_hash, |
| 260 bool is_manifest_stale, | 219 bool is_manifest_stale, |
| 261 const FinishCallback& finish_callback) { | 220 const FinishCallback& finish_callback) { |
| 262 installer->UpdateAsync(webapk_package, webapk_version, | 221 installer->UpdateAsync(webapk_package, webapk_version, |
| 263 icon_url_to_murmur2_hash, is_manifest_stale, | 222 icon_url_to_murmur2_hash, is_manifest_stale, |
| 264 finish_callback); | 223 finish_callback); |
| 265 } | 224 } |
| 266 | 225 |
| 267 void WebApkInstaller::SetTimeoutMs(int timeout_ms) { | 226 void WebApkInstaller::SetTimeoutMs(int timeout_ms) { |
| 268 webapk_download_url_timeout_ms_ = timeout_ms; | 227 webapk_server_timeout_ms_ = timeout_ms; |
| 269 download_timeout_ms_ = timeout_ms; | |
| 270 } | 228 } |
| 271 | 229 |
| 272 void WebApkInstaller::OnInstallFinished( | 230 void WebApkInstaller::OnInstallFinished( |
| 273 JNIEnv* env, | 231 JNIEnv* env, |
| 274 const base::android::JavaParamRef<jobject>& obj, | 232 const base::android::JavaParamRef<jobject>& obj, |
| 275 jint result) { | 233 jint result) { |
| 276 OnResult(static_cast<WebApkInstallResult>(result)); | 234 OnResult(static_cast<WebApkInstallResult>(result)); |
| 277 } | 235 } |
| 278 | 236 |
| 279 void WebApkInstaller::BuildWebApkProtoInBackgroundForTesting( | 237 void WebApkInstaller::BuildWebApkProtoInBackgroundForTesting( |
| 280 const base::Callback<void(std::unique_ptr<webapk::WebApk>)>& callback, | 238 const base::Callback<void(std::unique_ptr<webapk::WebApk>)>& callback, |
| 281 const std::map<std::string, std::string>& icon_url_to_murmur2_hash, | 239 const std::map<std::string, std::string>& icon_url_to_murmur2_hash, |
| 282 bool is_manifest_stale) { | 240 bool is_manifest_stale) { |
| 283 base::PostTaskAndReplyWithResult( | 241 base::PostTaskAndReplyWithResult( |
| 284 GetBackgroundTaskRunner().get(), FROM_HERE, | 242 GetBackgroundTaskRunner().get(), FROM_HERE, |
| 285 base::Bind(&BuildWebApkProtoInBackground, shortcut_info_, shortcut_icon_, | 243 base::Bind(&BuildWebApkProtoInBackground, shortcut_info_, shortcut_icon_, |
| 286 icon_url_to_murmur2_hash, is_manifest_stale), | 244 icon_url_to_murmur2_hash, is_manifest_stale), |
| 287 base::Bind(&OnWebApkProtoBuilt, callback)); | 245 base::Bind(&OnWebApkProtoBuilt, callback)); |
| 288 } | 246 } |
| 289 | 247 |
| 290 // static | 248 // static |
| 291 bool WebApkInstaller::Register(JNIEnv* env) { | 249 bool WebApkInstaller::Register(JNIEnv* env) { |
| 292 return RegisterNativesImpl(env); | 250 return RegisterNativesImpl(env); |
| 293 } | 251 } |
| 294 | 252 |
| 295 void WebApkInstaller::InstallDownloadedWebApk( | 253 bool WebApkInstaller::CanInstallWebApks() { |
| 296 JNIEnv* env, | |
| 297 const base::android::ScopedJavaLocalRef<jstring>& java_file_path, | |
| 298 const base::android::ScopedJavaLocalRef<jstring>& java_package_name) { | |
| 299 Java_WebApkInstaller_installDownloadedWebApkAsync( | |
| 300 env, java_ref_, java_file_path, java_package_name); | |
| 301 } | |
| 302 | |
| 303 void WebApkInstaller::UpdateUsingDownloadedWebApk( | |
| 304 JNIEnv* env, | |
| 305 const base::android::ScopedJavaLocalRef<jstring>& java_file_path) { | |
| 306 Java_WebApkInstaller_updateUsingDownloadedWebApkAsync(env, java_ref_, | |
| 307 java_file_path); | |
| 308 } | |
| 309 | |
| 310 bool WebApkInstaller::CanUseGooglePlayInstallService() { | |
| 311 return ChromeWebApkHost::GetGooglePlayInstallState() == | 254 return ChromeWebApkHost::GetGooglePlayInstallState() == |
| 312 GooglePlayInstallState::SUPPORTED; | 255 GooglePlayInstallState::SUPPORTED; |
| 313 } | 256 } |
| 314 | 257 |
| 315 void WebApkInstaller::InstallOrUpdateWebApkFromGooglePlay( | 258 void WebApkInstaller::InstallOrUpdateWebApk(const std::string& package_name, |
| 316 const std::string& package_name, | 259 int version, |
| 317 int version, | 260 const std::string& token) { |
| 318 const std::string& token) { | |
| 319 webapk_package_ = package_name; | 261 webapk_package_ = package_name; |
| 320 | 262 |
| 321 JNIEnv* env = base::android::AttachCurrentThread(); | 263 JNIEnv* env = base::android::AttachCurrentThread(); |
| 322 base::android::ScopedJavaLocalRef<jstring> java_webapk_package = | 264 base::android::ScopedJavaLocalRef<jstring> java_webapk_package = |
| 323 base::android::ConvertUTF8ToJavaString(env, webapk_package_); | 265 base::android::ConvertUTF8ToJavaString(env, webapk_package_); |
| 324 base::android::ScopedJavaLocalRef<jstring> java_title = | 266 base::android::ScopedJavaLocalRef<jstring> java_title = |
| 325 base::android::ConvertUTF16ToJavaString(env, shortcut_info_.user_title); | 267 base::android::ConvertUTF16ToJavaString(env, shortcut_info_.user_title); |
| 326 base::android::ScopedJavaLocalRef<jstring> java_token = | 268 base::android::ScopedJavaLocalRef<jstring> java_token = |
| 327 base::android::ConvertUTF8ToJavaString(env, token); | 269 base::android::ConvertUTF8ToJavaString(env, token); |
| 328 base::android::ScopedJavaLocalRef<jstring> java_url = | 270 base::android::ScopedJavaLocalRef<jstring> java_url = |
| 329 base::android::ConvertUTF8ToJavaString(env, shortcut_info_.url.spec()); | 271 base::android::ConvertUTF8ToJavaString(env, shortcut_info_.url.spec()); |
| 330 | 272 |
| 331 if (task_type_ == WebApkInstaller::INSTALL) { | 273 if (task_type_ == WebApkInstaller::INSTALL) { |
| 332 Java_WebApkInstaller_installWebApkFromGooglePlayAsync( | 274 Java_WebApkInstaller_installWebApkAsync(env, java_ref_, java_webapk_package, |
| 333 env, java_ref_, java_webapk_package, version, java_title, java_token, | 275 version, java_title, java_token, |
| 334 java_url); | 276 java_url); |
| 335 } else { | 277 } else { |
| 336 Java_WebApkInstaller_updateAsyncFromGooglePlay( | 278 Java_WebApkInstaller_updateAsync(env, java_ref_, java_webapk_package, |
| 337 env, java_ref_, java_webapk_package, version, java_title, java_token, | 279 version, java_title, java_token, java_url); |
| 338 java_url); | |
| 339 } | 280 } |
| 340 } | 281 } |
| 341 | 282 |
| 342 void WebApkInstaller::OnResult(WebApkInstallResult result) { | 283 void WebApkInstaller::OnResult(WebApkInstallResult result) { |
| 343 weak_ptr_factory_.InvalidateWeakPtrs(); | 284 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 344 finish_callback_.Run(result, relax_updates_, webapk_package_); | 285 finish_callback_.Run(result, relax_updates_, webapk_package_); |
| 345 delete this; | 286 delete this; |
| 346 } | 287 } |
| 347 | 288 |
| 348 WebApkInstaller::WebApkInstaller(content::BrowserContext* browser_context, | 289 WebApkInstaller::WebApkInstaller(content::BrowserContext* browser_context, |
| 349 const ShortcutInfo& shortcut_info, | 290 const ShortcutInfo& shortcut_info, |
| 350 const SkBitmap& shortcut_icon) | 291 const SkBitmap& shortcut_icon) |
| 351 : request_context_getter_( | 292 : request_context_getter_( |
| 352 Profile::FromBrowserContext(browser_context)->GetRequestContext()), | 293 Profile::FromBrowserContext(browser_context)->GetRequestContext()), |
| 353 shortcut_info_(shortcut_info), | 294 shortcut_info_(shortcut_info), |
| 354 shortcut_icon_(shortcut_icon), | 295 shortcut_icon_(shortcut_icon), |
| 355 server_url_(GetServerUrl()), | 296 server_url_(GetServerUrl()), |
| 356 webapk_download_url_timeout_ms_(kWebApkDownloadUrlTimeoutMs), | 297 webapk_server_timeout_ms_(kWebApkDownloadUrlTimeoutMs), |
| 357 download_timeout_ms_(kDownloadTimeoutMs), | |
| 358 relax_updates_(false), | 298 relax_updates_(false), |
| 359 webapk_version_(kDefaultWebApkVersion), | |
| 360 task_type_(UNDEFINED), | 299 task_type_(UNDEFINED), |
| 361 weak_ptr_factory_(this) { | 300 weak_ptr_factory_(this) { |
| 362 CreateJavaRef(); | 301 CreateJavaRef(); |
| 363 } | 302 } |
| 364 | 303 |
| 365 void WebApkInstaller::CreateJavaRef() { | 304 void WebApkInstaller::CreateJavaRef() { |
| 366 JNIEnv* env = base::android::AttachCurrentThread(); | 305 JNIEnv* env = base::android::AttachCurrentThread(); |
| 367 java_ref_.Reset( | 306 java_ref_.Reset( |
| 368 Java_WebApkInstaller_create(env, reinterpret_cast<intptr_t>(this))); | 307 Java_WebApkInstaller_create(env, reinterpret_cast<intptr_t>(this))); |
| 369 } | 308 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 383 DownloadAppIconAndComputeMurmur2Hash(); | 322 DownloadAppIconAndComputeMurmur2Hash(); |
| 384 } | 323 } |
| 385 | 324 |
| 386 void WebApkInstaller::UpdateAsync( | 325 void WebApkInstaller::UpdateAsync( |
| 387 const std::string& webapk_package, | 326 const std::string& webapk_package, |
| 388 int webapk_version, | 327 int webapk_version, |
| 389 const std::map<std::string, std::string>& icon_url_to_murmur2_hash, | 328 const std::map<std::string, std::string>& icon_url_to_murmur2_hash, |
| 390 bool is_manifest_stale, | 329 bool is_manifest_stale, |
| 391 const FinishCallback& finish_callback) { | 330 const FinishCallback& finish_callback) { |
| 392 webapk_package_ = webapk_package; | 331 webapk_package_ = webapk_package; |
| 393 webapk_version_ = webapk_version; | |
| 394 finish_callback_ = finish_callback; | 332 finish_callback_ = finish_callback; |
| 395 task_type_ = UPDATE; | 333 task_type_ = UPDATE; |
| 396 | 334 |
| 397 base::PostTaskAndReplyWithResult( | 335 base::PostTaskAndReplyWithResult( |
| 398 GetBackgroundTaskRunner().get(), FROM_HERE, | 336 GetBackgroundTaskRunner().get(), FROM_HERE, |
| 399 base::Bind(&BuildWebApkProtoInBackground, shortcut_info_, shortcut_icon_, | 337 base::Bind(&BuildWebApkProtoInBackground, shortcut_info_, shortcut_icon_, |
| 400 icon_url_to_murmur2_hash, is_manifest_stale), | 338 icon_url_to_murmur2_hash, is_manifest_stale), |
| 401 base::Bind(&WebApkInstaller::SendUpdateWebApkRequest, | 339 base::Bind(&WebApkInstaller::SendUpdateWebApkRequest, |
| 402 weak_ptr_factory_.GetWeakPtr())); | 340 weak_ptr_factory_.GetWeakPtr(), webapk_version)); |
| 403 } | 341 } |
| 404 | 342 |
| 405 void WebApkInstaller::OnURLFetchComplete(const net::URLFetcher* source) { | 343 void WebApkInstaller::OnURLFetchComplete(const net::URLFetcher* source) { |
| 406 timer_.Stop(); | 344 timer_.Stop(); |
| 407 | 345 |
| 408 if (!source->GetStatus().is_success() || | 346 if (!source->GetStatus().is_success() || |
| 409 source->GetResponseCode() != net::HTTP_OK) { | 347 source->GetResponseCode() != net::HTTP_OK) { |
| 410 LOG(WARNING) << base::StringPrintf( | 348 LOG(WARNING) << base::StringPrintf( |
| 411 "WebAPK server returned response code %d.", source->GetResponseCode()); | 349 "WebAPK server returned response code %d.", source->GetResponseCode()); |
| 412 OnResult(WebApkInstallResult::FAILURE); | 350 OnResult(WebApkInstallResult::FAILURE); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 431 OnResult(WebApkInstallResult::SUCCESS); | 369 OnResult(WebApkInstallResult::SUCCESS); |
| 432 return; | 370 return; |
| 433 } | 371 } |
| 434 | 372 |
| 435 if (!signed_download_url.is_valid() || response->package_name().empty()) { | 373 if (!signed_download_url.is_valid() || response->package_name().empty()) { |
| 436 LOG(WARNING) << "WebAPK server returned incomplete proto."; | 374 LOG(WARNING) << "WebAPK server returned incomplete proto."; |
| 437 OnResult(WebApkInstallResult::FAILURE); | 375 OnResult(WebApkInstallResult::FAILURE); |
| 438 return; | 376 return; |
| 439 } | 377 } |
| 440 | 378 |
| 441 if (CanUseGooglePlayInstallService()) { | 379 if (!CanInstallWebApks()) { |
| 442 int version = 1; | 380 OnResult(WebApkInstallResult::FAILURE); |
| 443 base::StringToInt(response->version(), &version); | |
| 444 InstallOrUpdateWebApkFromGooglePlay(response->package_name(), version, | |
| 445 response->token()); | |
| 446 return; | 381 return; |
| 447 } | 382 } |
| 448 | 383 |
| 449 OnGotWebApkDownloadUrl(signed_download_url, response->package_name()); | 384 int version = 1; |
| 385 base::StringToInt(response->version(), &version); |
| 386 InstallOrUpdateWebApk(response->package_name(), version, response->token()); |
| 450 } | 387 } |
| 451 | 388 |
| 452 void WebApkInstaller::DownloadAppIconAndComputeMurmur2Hash() { | 389 void WebApkInstaller::DownloadAppIconAndComputeMurmur2Hash() { |
| 453 icon_hasher_.reset(new WebApkIconHasher( | 390 icon_hasher_.reset(new WebApkIconHasher( |
| 454 request_context_getter_, shortcut_info_.best_primary_icon_url, | 391 request_context_getter_, shortcut_info_.best_primary_icon_url, |
| 455 base::Bind(&WebApkInstaller::OnGotIconMurmur2Hash, | 392 base::Bind(&WebApkInstaller::OnGotIconMurmur2Hash, |
| 456 weak_ptr_factory_.GetWeakPtr()))); | 393 weak_ptr_factory_.GetWeakPtr()))); |
| 457 icon_hasher_->DownloadAndComputeMurmur2Hash(); | 394 icon_hasher_->DownloadAndComputeMurmur2Hash(); |
| 458 } | 395 } |
| 459 | 396 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 482 base::Bind(&WebApkInstaller::SendCreateWebApkRequest, | 419 base::Bind(&WebApkInstaller::SendCreateWebApkRequest, |
| 483 weak_ptr_factory_.GetWeakPtr())); | 420 weak_ptr_factory_.GetWeakPtr())); |
| 484 } | 421 } |
| 485 | 422 |
| 486 void WebApkInstaller::SendCreateWebApkRequest( | 423 void WebApkInstaller::SendCreateWebApkRequest( |
| 487 std::unique_ptr<webapk::WebApk> webapk) { | 424 std::unique_ptr<webapk::WebApk> webapk) { |
| 488 SendRequest(std::move(webapk), server_url_); | 425 SendRequest(std::move(webapk), server_url_); |
| 489 } | 426 } |
| 490 | 427 |
| 491 void WebApkInstaller::SendUpdateWebApkRequest( | 428 void WebApkInstaller::SendUpdateWebApkRequest( |
| 429 int webapk_version, |
| 492 std::unique_ptr<webapk::WebApk> webapk) { | 430 std::unique_ptr<webapk::WebApk> webapk) { |
| 493 webapk->set_package_name(webapk_package_); | 431 webapk->set_package_name(webapk_package_); |
| 494 webapk->set_version(std::to_string(webapk_version_)); | 432 webapk->set_version(std::to_string(webapk_version)); |
| 495 | 433 |
| 496 SendRequest(std::move(webapk), server_url_); | 434 SendRequest(std::move(webapk), server_url_); |
| 497 } | 435 } |
| 498 | 436 |
| 499 void WebApkInstaller::SendRequest(std::unique_ptr<webapk::WebApk> request_proto, | 437 void WebApkInstaller::SendRequest(std::unique_ptr<webapk::WebApk> request_proto, |
| 500 const GURL& server_url) { | 438 const GURL& server_url) { |
| 501 timer_.Start( | 439 timer_.Start( |
| 502 FROM_HERE, | 440 FROM_HERE, base::TimeDelta::FromMilliseconds(webapk_server_timeout_ms_), |
| 503 base::TimeDelta::FromMilliseconds(webapk_download_url_timeout_ms_), | |
| 504 base::Bind(&WebApkInstaller::OnResult, weak_ptr_factory_.GetWeakPtr(), | 441 base::Bind(&WebApkInstaller::OnResult, weak_ptr_factory_.GetWeakPtr(), |
| 505 WebApkInstallResult::FAILURE)); | 442 WebApkInstallResult::FAILURE)); |
| 506 | 443 |
| 507 url_fetcher_ = | 444 url_fetcher_ = |
| 508 net::URLFetcher::Create(server_url, net::URLFetcher::POST, this); | 445 net::URLFetcher::Create(server_url, net::URLFetcher::POST, this); |
| 509 url_fetcher_->SetRequestContext(request_context_getter_); | 446 url_fetcher_->SetRequestContext(request_context_getter_); |
| 510 std::string serialized_request; | 447 std::string serialized_request; |
| 511 request_proto->SerializeToString(&serialized_request); | 448 request_proto->SerializeToString(&serialized_request); |
| 512 url_fetcher_->SetUploadData(kProtoMimeType, serialized_request); | 449 url_fetcher_->SetUploadData(kProtoMimeType, serialized_request); |
| 513 url_fetcher_->SetLoadFlags( | 450 url_fetcher_->SetLoadFlags( |
| 514 net::LOAD_DISABLE_CACHE | net::LOAD_DO_NOT_SEND_COOKIES | | 451 net::LOAD_DISABLE_CACHE | net::LOAD_DO_NOT_SEND_COOKIES | |
| 515 net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_AUTH_DATA); | 452 net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_AUTH_DATA); |
| 516 url_fetcher_->Start(); | 453 url_fetcher_->Start(); |
| 517 } | 454 } |
| 518 | |
| 519 void WebApkInstaller::OnGotWebApkDownloadUrl(const GURL& download_url, | |
| 520 const std::string& package_name) { | |
| 521 webapk_package_ = package_name; | |
| 522 | |
| 523 base::PostTaskAndReplyWithResult( | |
| 524 GetBackgroundTaskRunner().get(), FROM_HERE, | |
| 525 base::Bind(&CreateSubDirAndSetPermissionsInBackground, | |
| 526 task_type_ == WebApkInstaller::INSTALL ? "install" : "update", | |
| 527 package_name), | |
| 528 base::Bind(&WebApkInstaller::OnCreatedSubDirAndSetPermissions, | |
| 529 weak_ptr_factory_.GetWeakPtr(), download_url)); | |
| 530 } | |
| 531 | |
| 532 void WebApkInstaller::OnCreatedSubDirAndSetPermissions( | |
| 533 const GURL& download_url, | |
| 534 const base::FilePath& output_dir) { | |
| 535 if (output_dir.empty()) { | |
| 536 OnResult(WebApkInstallResult::FAILURE); | |
| 537 return; | |
| 538 } | |
| 539 | |
| 540 DownloadWebApk(output_dir.AppendASCII(webapk_package_ + ".apk"), download_url, | |
| 541 true); | |
| 542 } | |
| 543 | |
| 544 void WebApkInstaller::DownloadWebApk(const base::FilePath& output_path, | |
| 545 const GURL& download_url, | |
| 546 bool retry_if_fails) { | |
| 547 timer_.Start( | |
| 548 FROM_HERE, base::TimeDelta::FromMilliseconds(download_timeout_ms_), | |
| 549 base::Bind(&WebApkInstaller::OnResult, weak_ptr_factory_.GetWeakPtr(), | |
| 550 WebApkInstallResult::FAILURE)); | |
| 551 | |
| 552 downloader_.reset(new FileDownloader( | |
| 553 download_url, output_path, true, request_context_getter_, | |
| 554 base::Bind(&WebApkInstaller::OnWebApkDownloaded, | |
| 555 weak_ptr_factory_.GetWeakPtr(), output_path, download_url, | |
| 556 retry_if_fails), | |
| 557 NO_TRAFFIC_ANNOTATION_YET)); | |
| 558 } | |
| 559 | |
| 560 void WebApkInstaller::OnWebApkDownloaded(const base::FilePath& file_path, | |
| 561 const GURL& download_url, | |
| 562 bool retry_if_fails, | |
| 563 FileDownloader::Result result) { | |
| 564 timer_.Stop(); | |
| 565 | |
| 566 if (result != FileDownloader::DOWNLOADED) { | |
| 567 if (!retry_if_fails) { | |
| 568 OnResult(WebApkInstallResult::FAILURE); | |
| 569 return; | |
| 570 } | |
| 571 | |
| 572 content::BrowserThread::PostDelayedTask( | |
| 573 content::BrowserThread::UI, FROM_HERE, | |
| 574 base::Bind(&WebApkInstaller::DownloadWebApk, | |
| 575 weak_ptr_factory_.GetWeakPtr(), file_path, download_url, | |
| 576 false), | |
| 577 base::TimeDelta::FromSeconds(2)); | |
| 578 return; | |
| 579 } | |
| 580 | |
| 581 int posix_permissions = kWorldReadableFilePermission | | |
| 582 base::FILE_PERMISSION_WRITE_BY_USER | | |
| 583 base::FILE_PERMISSION_EXECUTE_BY_USER; | |
| 584 base::PostTaskAndReplyWithResult( | |
| 585 GetBackgroundTaskRunner().get(), FROM_HERE, | |
| 586 base::Bind(&base::SetPosixFilePermissions, file_path, posix_permissions), | |
| 587 base::Bind(&WebApkInstaller::OnWebApkMadeWorldReadable, | |
| 588 weak_ptr_factory_.GetWeakPtr(), file_path)); | |
| 589 } | |
| 590 | |
| 591 void WebApkInstaller::OnWebApkMadeWorldReadable( | |
| 592 const base::FilePath& file_path, | |
| 593 bool change_permission_success) { | |
| 594 if (!change_permission_success) { | |
| 595 OnResult(WebApkInstallResult::FAILURE); | |
| 596 return; | |
| 597 } | |
| 598 | |
| 599 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 600 base::android::ScopedJavaLocalRef<jstring> java_file_path = | |
| 601 base::android::ConvertUTF8ToJavaString(env, file_path.value()); | |
| 602 if (task_type_ == INSTALL) { | |
| 603 base::android::ScopedJavaLocalRef<jstring> java_package_name = | |
| 604 base::android::ConvertUTF8ToJavaString(env, webapk_package_); | |
| 605 InstallDownloadedWebApk(env, java_file_path, java_package_name); | |
| 606 } else if (task_type_ == UPDATE) { | |
| 607 UpdateUsingDownloadedWebApk(env, java_file_path); | |
| 608 } | |
| 609 } | |
| OLD | NEW |