Chromium Code Reviews| 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 10 matching lines...) Expand all Loading... | |
| 21 #include "base/threading/sequenced_worker_pool.h" | 21 #include "base/threading/sequenced_worker_pool.h" |
| 22 #include "chrome/browser/android/shortcut_helper.h" | 22 #include "chrome/browser/android/shortcut_helper.h" |
| 23 #include "chrome/browser/android/webapk/webapk.pb.h" | 23 #include "chrome/browser/android/webapk/webapk.pb.h" |
| 24 #include "chrome/browser/profiles/profile.h" | 24 #include "chrome/browser/profiles/profile.h" |
| 25 #include "chrome/common/chrome_switches.h" | 25 #include "chrome/common/chrome_switches.h" |
| 26 #include "components/version_info/version_info.h" | 26 #include "components/version_info/version_info.h" |
| 27 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
| 28 #include "content/public/common/manifest_util.h" | 28 #include "content/public/common/manifest_util.h" |
| 29 #include "jni/WebApkInstaller_jni.h" | 29 #include "jni/WebApkInstaller_jni.h" |
| 30 #include "net/http/http_status_code.h" | 30 #include "net/http/http_status_code.h" |
| 31 #include "net/url_request/url_fetcher.h" | |
| 32 #include "third_party/smhasher/src/MurmurHash2.h" | 31 #include "third_party/smhasher/src/MurmurHash2.h" |
| 33 #include "ui/gfx/codec/png_codec.h" | 32 #include "ui/gfx/codec/png_codec.h" |
| 34 #include "url/gurl.h" | 33 #include "url/gurl.h" |
| 35 | 34 |
| 36 namespace { | 35 namespace { |
| 37 | 36 |
| 38 // The default WebAPK server URL. | 37 // The default WebAPK server URL. |
| 39 const char kDefaultWebApkServerUrl[] = | 38 const char kDefaultWebApkServerUrl[] = |
| 40 "https://webapk.googleapis.com/v1alpha/webApks?alt=proto"; | 39 "https://webapk.googleapis.com/v1alpha/webApks/"; |
| 40 | |
| 41 // The response format type expected from the WebAPK server. | |
| 42 const char kDefaultWebApkServerUrlResponseType[] = "?alt=proto"; | |
| 41 | 43 |
| 42 // The MIME type of the POST data sent to the server. | 44 // The MIME type of the POST data sent to the server. |
| 43 const char kProtoMimeType[] = "application/x-protobuf"; | 45 const char kProtoMimeType[] = "application/x-protobuf"; |
| 44 | 46 |
| 45 // The seed to use the murmur2 hash of the app icon. | 47 // The seed to use the murmur2 hash of the app icon. |
| 46 const uint32_t kMurmur2HashSeed = 0; | 48 const uint32_t kMurmur2HashSeed = 0; |
| 47 | 49 |
| 48 // The default number of milliseconds to wait for the WebAPK download URL from | 50 // The default number of milliseconds to wait for the WebAPK download URL from |
| 49 // the WebAPK server. | 51 // the WebAPK server. |
| 50 const int kWebApkDownloadUrlTimeoutMs = 60000; | 52 const int kWebApkDownloadUrlTimeoutMs = 60000; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 77 return ""; | 79 return ""; |
| 78 | 80 |
| 79 SkColor sk_color = reinterpret_cast<uint32_t&>(color); | 81 SkColor sk_color = reinterpret_cast<uint32_t&>(color); |
| 80 int r = SkColorGetR(sk_color); | 82 int r = SkColorGetR(sk_color); |
| 81 int g = SkColorGetG(sk_color); | 83 int g = SkColorGetG(sk_color); |
| 82 int b = SkColorGetB(sk_color); | 84 int b = SkColorGetB(sk_color); |
| 83 double a = SkColorGetA(sk_color) / 255.0; | 85 double a = SkColorGetA(sk_color) / 255.0; |
| 84 return base::StringPrintf("rgba(%d,%d,%d,%.2f)", r, g, b, a); | 86 return base::StringPrintf("rgba(%d,%d,%d,%.2f)", r, g, b, a); |
| 85 } | 87 } |
| 86 | 88 |
| 89 GURL GetServerUrlForUpdate(const GURL& server_url, | |
| 90 const std::string& webapk_package) { | |
| 91 return GURL(server_url.spec() + webapk_package + "/" + | |
|
Yaron
2016/08/12 21:16:17
i see what you're saying now about the url. I thin
Xi Han
2016/08/15 21:38:45
Yes, I added the bug number back.
| |
| 92 kDefaultWebApkServerUrlResponseType); | |
| 93 } | |
| 94 | |
| 87 } // anonymous namespace | 95 } // anonymous namespace |
| 88 | 96 |
| 89 WebApkInstaller::WebApkInstaller(const ShortcutInfo& shortcut_info, | 97 WebApkInstaller::WebApkInstaller(const ShortcutInfo& shortcut_info, |
| 90 const SkBitmap& shortcut_icon) | 98 const SkBitmap& shortcut_icon) |
| 91 : shortcut_info_(shortcut_info), | 99 : shortcut_info_(shortcut_info), |
| 92 shortcut_icon_(shortcut_icon), | 100 shortcut_icon_(shortcut_icon), |
| 93 webapk_download_url_timeout_ms_(kWebApkDownloadUrlTimeoutMs), | 101 webapk_download_url_timeout_ms_(kWebApkDownloadUrlTimeoutMs), |
| 94 download_timeout_ms_(kDownloadTimeoutMs), | 102 download_timeout_ms_(kDownloadTimeoutMs), |
| 103 task_type_(UNDEFINED), | |
| 95 weak_ptr_factory_(this) { | 104 weak_ptr_factory_(this) { |
| 96 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 105 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| 97 server_url_ = | 106 server_url_ = |
| 98 GURL(command_line->HasSwitch(switches::kWebApkServerUrl) | 107 GURL(command_line->HasSwitch(switches::kWebApkServerUrl) |
| 99 ? command_line->GetSwitchValueASCII(switches::kWebApkServerUrl) | 108 ? command_line->GetSwitchValueASCII(switches::kWebApkServerUrl) |
| 100 : kDefaultWebApkServerUrl); | 109 : kDefaultWebApkServerUrl); |
| 101 } | 110 } |
| 102 | 111 |
| 103 WebApkInstaller::~WebApkInstaller() {} | 112 WebApkInstaller::~WebApkInstaller() {} |
| 104 | 113 |
| 105 void WebApkInstaller::InstallAsync(content::BrowserContext* browser_context, | 114 void WebApkInstaller::InstallAsync(content::BrowserContext* browser_context, |
| 106 const FinishCallback& finish_callback) { | 115 const FinishCallback& finish_callback) { |
| 107 InstallAsyncWithURLRequestContextGetter( | 116 InstallAsyncWithURLRequestContextGetter( |
|
Yaron
2016/08/12 21:16:17
there's no thread-hopping anymore - can we just in
Xi Han
2016/08/15 21:38:45
The |InstallAsyncWithURLRequestContextGetter| is w
Yaron
2016/08/16 00:32:03
got it, thanks
| |
| 108 Profile::FromBrowserContext(browser_context)->GetRequestContext(), | 117 Profile::FromBrowserContext(browser_context)->GetRequestContext(), |
| 109 finish_callback); | 118 finish_callback); |
| 110 } | 119 } |
| 111 | 120 |
| 112 void WebApkInstaller::InstallAsyncWithURLRequestContextGetter( | 121 void WebApkInstaller::InstallAsyncWithURLRequestContextGetter( |
| 113 net::URLRequestContextGetter* request_context_getter, | 122 net::URLRequestContextGetter* request_context_getter, |
| 114 const FinishCallback& finish_callback) { | 123 const FinishCallback& finish_callback) { |
| 115 request_context_getter_ = request_context_getter; | 124 request_context_getter_ = request_context_getter; |
| 116 finish_callback_ = finish_callback; | 125 finish_callback_ = finish_callback; |
| 126 task_type_ = INSTALL; | |
| 117 | 127 |
| 118 // base::Unretained() is safe because WebApkInstaller owns itself and does not | 128 // base::Unretained() is safe because WebApkInstaller owns itself and does not |
| 119 // start the timeout timer till after SendCreateWebApkRequest() is called. | 129 // start the timeout timer till after SendCreateWebApkRequest() is called. |
| 120 scoped_refptr<base::TaskRunner> background_task_runner = | 130 scoped_refptr<base::TaskRunner> background_task_runner = |
| 121 content::BrowserThread::GetBlockingPool() | 131 content::BrowserThread::GetBlockingPool() |
| 122 ->GetTaskRunnerWithShutdownBehavior( | 132 ->GetTaskRunnerWithShutdownBehavior( |
| 123 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); | 133 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); |
| 124 base::PostTaskAndReplyWithResult( | 134 base::PostTaskAndReplyWithResult( |
| 125 background_task_runner.get(), FROM_HERE, | 135 background_task_runner.get(), FROM_HERE, |
| 126 base::Bind(&WebApkInstaller::BuildWebApkProtoInBackground, | 136 base::Bind(&WebApkInstaller::BuildWebApkProtoInBackground, |
| 127 base::Unretained(this)), | 137 base::Unretained(this)), |
| 128 base::Bind(&WebApkInstaller::SendCreateWebApkRequest, | 138 base::Bind(&WebApkInstaller::SendCreateWebApkRequest, |
| 129 base::Unretained(this))); | 139 base::Unretained(this))); |
| 130 } | 140 } |
| 131 | 141 |
| 132 void WebApkInstaller::SetTimeoutMs(int timeout_ms) { | 142 void WebApkInstaller::SetTimeoutMs(int timeout_ms) { |
| 133 webapk_download_url_timeout_ms_ = timeout_ms; | 143 webapk_download_url_timeout_ms_ = timeout_ms; |
| 134 download_timeout_ms_ = timeout_ms; | 144 download_timeout_ms_ = timeout_ms; |
| 135 } | 145 } |
| 136 | 146 |
| 137 bool WebApkInstaller::StartDownloadedWebApkInstall( | 147 void WebApkInstaller::UpdateAsync(content::BrowserContext* browser_context, |
| 148 const FinishCallback& finish_callback, | |
| 149 const std::string& webapk_package, | |
| 150 int webapk_version) { | |
| 151 UpdateAsyncWithURLRequestContextGetter( | |
| 152 Profile::FromBrowserContext(browser_context)->GetRequestContext(), | |
| 153 finish_callback, webapk_package, webapk_version); | |
| 154 } | |
| 155 | |
| 156 void WebApkInstaller::UpdateAsyncWithURLRequestContextGetter( | |
| 157 net::URLRequestContextGetter* request_context_getter, | |
| 158 const FinishCallback& finish_callback, | |
| 159 const std::string& webapk_package, | |
| 160 int webapk_version) { | |
| 161 request_context_getter_ = request_context_getter; | |
| 162 finish_callback_ = finish_callback; | |
| 163 webapk_package_ = webapk_package; | |
| 164 webapk_version_ = webapk_version; | |
| 165 task_type_ = UPDATE; | |
| 166 | |
|
pkotwicz
2016/08/11 22:02:44
Nit: You can steal GetBackgroundTaskRunner() from
Xi Han
2016/08/15 21:38:45
Done.
| |
| 167 // base::Unretained() is safe because WebApkInstaller owns itself and does not | |
| 168 // start the timeout timer till after SendUpdateWebApkRequest() is called. | |
| 169 scoped_refptr<base::TaskRunner> background_task_runner = | |
| 170 content::BrowserThread::GetBlockingPool() | |
| 171 ->GetTaskRunnerWithShutdownBehavior( | |
| 172 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); | |
| 173 base::PostTaskAndReplyWithResult( | |
| 174 background_task_runner.get(), FROM_HERE, | |
| 175 base::Bind(&WebApkInstaller::BuildWebApkProtoInBackground, | |
| 176 base::Unretained(this)), | |
| 177 base::Bind(&WebApkInstaller::SendUpdateWebApkRequest, | |
| 178 base::Unretained(this))); | |
| 179 } | |
| 180 | |
| 181 bool WebApkInstaller::StartInstallingDownloadedWebApk( | |
| 138 JNIEnv* env, | 182 JNIEnv* env, |
| 139 const base::android::ScopedJavaLocalRef<jstring>& java_file_path, | 183 const base::android::ScopedJavaLocalRef<jstring>& java_file_path, |
| 140 const base::android::ScopedJavaLocalRef<jstring>& java_package_name) { | 184 const base::android::ScopedJavaLocalRef<jstring>& java_package_name) { |
| 141 return Java_WebApkInstaller_installAsyncFromNative(env, java_file_path.obj(), | 185 return Java_WebApkInstaller_installAsyncFromNative(env, java_file_path.obj(), |
| 142 java_package_name.obj()); | 186 java_package_name.obj()); |
| 143 } | 187 } |
| 144 | 188 |
| 189 bool WebApkInstaller::StartUpdateUsingDownloadedWebApk( | |
| 190 JNIEnv* env, | |
| 191 const base::android::ScopedJavaLocalRef<jstring>& java_file_path, | |
| 192 const base::android::ScopedJavaLocalRef<jstring>& java_package_name) { | |
| 193 return Java_WebApkInstaller_updateAsyncFromNative(env, java_file_path.obj(), | |
| 194 java_package_name.obj()); | |
| 195 } | |
| 196 | |
| 145 void WebApkInstaller::OnURLFetchComplete(const net::URLFetcher* source) { | 197 void WebApkInstaller::OnURLFetchComplete(const net::URLFetcher* source) { |
| 146 timer_.Stop(); | 198 timer_.Stop(); |
| 147 | 199 |
| 148 if (!source->GetStatus().is_success() || | 200 if (!source->GetStatus().is_success() || |
| 149 source->GetResponseCode() != net::HTTP_OK) { | 201 source->GetResponseCode() != net::HTTP_OK) { |
| 150 OnFailure(); | 202 OnFailure(); |
| 151 return; | 203 return; |
| 152 } | 204 } |
| 153 | 205 |
| 154 std::string response_string; | 206 std::string response_string; |
| 155 source->GetResponseAsString(&response_string); | 207 source->GetResponseAsString(&response_string); |
| 156 | 208 |
| 157 std::unique_ptr<webapk::WebApkResponse> response( | 209 std::unique_ptr<webapk::WebApkResponse> response( |
| 158 new webapk::WebApkResponse); | 210 new webapk::WebApkResponse); |
| 159 if (!response->ParseFromString(response_string)) { | 211 if (!response->ParseFromString(response_string)) { |
| 160 OnFailure(); | 212 OnFailure(); |
| 161 return; | 213 return; |
| 162 } | 214 } |
| 163 | 215 |
| 164 GURL signed_download_url(response->signed_download_url()); | 216 GURL signed_download_url(response->signed_download_url()); |
| 165 if (!signed_download_url.is_valid() || response->package_name().empty()) { | 217 if (!signed_download_url.is_valid() || response->package_name().empty()) { |
| 166 OnFailure(); | 218 OnFailure(); |
| 167 return; | 219 return; |
| 168 } | 220 } |
| 169 OnGotWebApkDownloadUrl(signed_download_url, response->package_name()); | 221 OnGotWebApkDownloadUrl(signed_download_url, response->package_name()); |
| 170 } | 222 } |
| 171 | 223 |
| 172 void WebApkInstaller::SendCreateWebApkRequest( | 224 void WebApkInstaller::SendCreateWebApkRequest( |
| 173 std::unique_ptr<webapk::WebApk> webapk_proto) { | 225 std::unique_ptr<webapk::WebApk> webapk) { |
| 226 GURL server_url(server_url_.spec() + kDefaultWebApkServerUrlResponseType); | |
| 227 SendRequest(std::move(webapk), net::URLFetcher::POST, server_url); | |
| 228 } | |
| 229 | |
| 230 void WebApkInstaller::SendUpdateWebApkRequest( | |
| 231 std::unique_ptr<webapk::WebApk> webapk) { | |
| 232 webapk->set_package_name(webapk_package_); | |
| 233 webapk->set_version(std::to_string(webapk_version_)); | |
| 234 | |
| 235 SendRequest(std::move(webapk), net::URLFetcher::PUT, | |
| 236 GetServerUrlForUpdate(server_url_, webapk_package_)); | |
| 237 } | |
| 238 | |
| 239 void WebApkInstaller::SendRequest(std::unique_ptr<webapk::WebApk> request_proto, | |
| 240 net::URLFetcher::RequestType request_type, | |
| 241 const GURL& server_url) { | |
| 174 timer_.Start( | 242 timer_.Start( |
| 175 FROM_HERE, | 243 FROM_HERE, |
| 176 base::TimeDelta::FromMilliseconds(webapk_download_url_timeout_ms_), | 244 base::TimeDelta::FromMilliseconds(webapk_download_url_timeout_ms_), |
| 177 base::Bind(&WebApkInstaller::OnTimeout, weak_ptr_factory_.GetWeakPtr())); | 245 base::Bind(&WebApkInstaller::OnTimeout, weak_ptr_factory_.GetWeakPtr())); |
| 178 | 246 |
| 179 url_fetcher_ = | 247 url_fetcher_ = net::URLFetcher::Create(server_url, request_type, this); |
| 180 net::URLFetcher::Create(server_url_, net::URLFetcher::POST, this); | |
| 181 url_fetcher_->SetRequestContext(request_context_getter_); | 248 url_fetcher_->SetRequestContext(request_context_getter_); |
| 182 std::string serialized_request; | 249 std::string serialized_request; |
| 183 webapk_proto->SerializeToString(&serialized_request); | 250 request_proto->SerializeToString(&serialized_request); |
| 184 url_fetcher_->SetUploadData(kProtoMimeType, serialized_request); | 251 url_fetcher_->SetUploadData(kProtoMimeType, serialized_request); |
| 185 url_fetcher_->Start(); | 252 url_fetcher_->Start(); |
| 186 } | 253 } |
| 187 | 254 |
| 188 void WebApkInstaller::OnGotWebApkDownloadUrl(const GURL& download_url, | 255 void WebApkInstaller::OnGotWebApkDownloadUrl(const GURL& download_url, |
| 189 const std::string& package_name) { | 256 const std::string& package_name) { |
| 190 base::FilePath output_dir; | 257 base::FilePath output_dir; |
| 191 base::android::GetCacheDirectory(&output_dir); | 258 base::android::GetCacheDirectory(&output_dir); |
| 192 // TODO(pkotwicz): Download WebAPKs into WebAPK-specific subdirectory | 259 // TODO(pkotwicz): Download WebAPKs into WebAPK-specific subdirectory |
| 193 // directory. | 260 // directory. |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 212 if (result != FileDownloader::DOWNLOADED) { | 279 if (result != FileDownloader::DOWNLOADED) { |
| 213 OnFailure(); | 280 OnFailure(); |
| 214 return; | 281 return; |
| 215 } | 282 } |
| 216 | 283 |
| 217 JNIEnv* env = base::android::AttachCurrentThread(); | 284 JNIEnv* env = base::android::AttachCurrentThread(); |
| 218 base::android::ScopedJavaLocalRef<jstring> java_file_path = | 285 base::android::ScopedJavaLocalRef<jstring> java_file_path = |
| 219 base::android::ConvertUTF8ToJavaString(env, file_path.value()); | 286 base::android::ConvertUTF8ToJavaString(env, file_path.value()); |
| 220 base::android::ScopedJavaLocalRef<jstring> java_package_name = | 287 base::android::ScopedJavaLocalRef<jstring> java_package_name = |
| 221 base::android::ConvertUTF8ToJavaString(env, package_name); | 288 base::android::ConvertUTF8ToJavaString(env, package_name); |
| 222 bool success = | 289 bool success = false; |
| 223 StartDownloadedWebApkInstall(env, java_file_path, java_package_name); | 290 if (task_type_ == INSTALL) { |
| 291 success = | |
| 292 StartInstallingDownloadedWebApk(env, java_file_path, java_package_name); | |
| 293 } else if (task_type_ == UPDATE) { | |
| 294 success = StartUpdateUsingDownloadedWebApk(env, java_file_path, | |
| 295 java_package_name); | |
| 296 } | |
| 224 if (success) | 297 if (success) |
| 225 OnSuccess(); | 298 OnSuccess(); |
| 226 else | 299 else |
| 227 OnFailure(); | 300 OnFailure(); |
| 228 } | 301 } |
| 229 | 302 |
| 230 std::unique_ptr<webapk::WebApk> | 303 std::unique_ptr<webapk::WebApk> |
| 231 WebApkInstaller::BuildWebApkProtoInBackground() { | 304 WebApkInstaller::BuildWebApkProtoInBackground() { |
| 232 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); | 305 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); |
| 233 | 306 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 271 | 344 |
| 272 void WebApkInstaller::OnSuccess() { | 345 void WebApkInstaller::OnSuccess() { |
| 273 finish_callback_.Run(true); | 346 finish_callback_.Run(true); |
| 274 delete this; | 347 delete this; |
| 275 } | 348 } |
| 276 | 349 |
| 277 void WebApkInstaller::OnFailure() { | 350 void WebApkInstaller::OnFailure() { |
| 278 finish_callback_.Run(false); | 351 finish_callback_.Run(false); |
| 279 delete this; | 352 delete this; |
| 280 } | 353 } |
| OLD | NEW |