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 |