| 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 <jni.h> | 7 #include <jni.h> |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include <string> | 9 #include <string> |
| 10 | 10 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 base::Bind(&TestWebApkInstaller::OnSuccess, base::Unretained(this))); | 95 base::Bind(&TestWebApkInstaller::OnSuccess, base::Unretained(this))); |
| 96 } | 96 } |
| 97 | 97 |
| 98 private: | 98 private: |
| 99 // Whether the Google Play install delegate is available. | 99 // Whether the Google Play install delegate is available. |
| 100 bool has_google_play_webapk_install_delegate_; | 100 bool has_google_play_webapk_install_delegate_; |
| 101 | 101 |
| 102 DISALLOW_COPY_AND_ASSIGN(TestWebApkInstaller); | 102 DISALLOW_COPY_AND_ASSIGN(TestWebApkInstaller); |
| 103 }; | 103 }; |
| 104 | 104 |
| 105 } // anonymous namespace |
| 106 |
| 105 // Runs the WebApkInstaller installation process/update and blocks till done. | 107 // Runs the WebApkInstaller installation process/update and blocks till done. |
| 106 class WebApkInstallerRunner { | 108 class WebApkInstallerRunner { |
| 107 public: | 109 public: |
| 108 explicit WebApkInstallerRunner(const GURL& best_icon_url) | 110 explicit WebApkInstallerRunner(const GURL& best_icon_url) |
| 109 : url_request_context_getter_(new net::TestURLRequestContextGetter( | 111 : url_request_context_getter_(new net::TestURLRequestContextGetter( |
| 110 base::ThreadTaskRunnerHandle::Get())), | 112 base::ThreadTaskRunnerHandle::Get())), |
| 111 best_icon_url_(best_icon_url), | 113 best_icon_url_(best_icon_url), |
| 112 has_google_play_webapk_install_delegate_(false) {} | 114 has_google_play_webapk_install_delegate_(false) {} |
| 113 | 115 |
| 114 ~WebApkInstallerRunner() {} | 116 ~WebApkInstallerRunner() {} |
| (...skipping 10 matching lines...) Expand all Loading... |
| 125 base::Bind(&WebApkInstallerRunner::OnCompleted, | 127 base::Bind(&WebApkInstallerRunner::OnCompleted, |
| 126 base::Unretained(this))); | 128 base::Unretained(this))); |
| 127 Run(); | 129 Run(); |
| 128 } | 130 } |
| 129 | 131 |
| 130 void RunUpdateWebApk() { | 132 void RunUpdateWebApk() { |
| 131 const std::string kIconMurmur2Hash = "0"; | 133 const std::string kIconMurmur2Hash = "0"; |
| 132 const int kWebApkVersion = 1; | 134 const int kWebApkVersion = 1; |
| 133 | 135 |
| 134 WebApkInstaller* installer = CreateWebApkInstaller(); | 136 WebApkInstaller* installer = CreateWebApkInstaller(); |
| 137 std::map<std::string, std::string> icon_url_to_murmur2_hash_map; |
| 138 icon_url_to_murmur2_hash_map[best_icon_url_.spec()] = kIconMurmur2Hash; |
| 135 | 139 |
| 136 installer->UpdateAsyncWithURLRequestContextGetter( | 140 installer->UpdateAsyncWithURLRequestContextGetter( |
| 137 url_request_context_getter_.get(), | 141 url_request_context_getter_.get(), |
| 138 base::Bind(&WebApkInstallerRunner::OnCompleted, base::Unretained(this)), | 142 base::Bind(&WebApkInstallerRunner::OnCompleted, base::Unretained(this)), |
| 139 kIconMurmur2Hash, | |
| 140 kDownloadedWebApkPackageName, | 143 kDownloadedWebApkPackageName, |
| 141 kWebApkVersion); | 144 kWebApkVersion, |
| 145 false /* stale_manifest */, |
| 146 icon_url_to_murmur2_hash_map); |
| 142 | 147 |
| 143 Run(); | 148 Run(); |
| 144 } | 149 } |
| 145 | 150 |
| 146 WebApkInstaller* CreateWebApkInstaller() { | 151 WebApkInstaller* CreateWebApkInstaller() { |
| 147 ShortcutInfo info(GURL::EmptyGURL()); | 152 ShortcutInfo info(GURL::EmptyGURL()); |
| 148 info.best_icon_url = best_icon_url_; | 153 info.best_icon_url = best_icon_url_; |
| 149 | 154 |
| 150 // WebApkInstaller owns itself. | 155 // WebApkInstaller owns itself. |
| 151 WebApkInstaller* installer = new TestWebApkInstaller( | 156 WebApkInstaller* installer = new TestWebApkInstaller( |
| 152 info, SkBitmap(), has_google_play_webapk_install_delegate_); | 157 info, SkBitmap(), has_google_play_webapk_install_delegate_); |
| 153 installer->SetTimeoutMs(100); | 158 installer->SetTimeoutMs(100); |
| 154 return installer; | 159 return installer; |
| 155 } | 160 } |
| 156 | 161 |
| 162 // Populates a webapk::WebApk. |
| 163 void BuildWebApkProto( |
| 164 const GURL& best_icon_url, |
| 165 bool stale_manifest, |
| 166 const std::map<std::string, std::string> icon_url_to_murmur2_hash_map) { |
| 167 ShortcutInfo shortcut_info(GURL::EmptyGURL()); |
| 168 shortcut_info.best_icon_url = best_icon_url; |
| 169 |
| 170 base::PostTaskAndReplyWithResult( |
| 171 GetBackgroundTaskRunner().get(), FROM_HERE, |
| 172 base::Bind(&WebApkInstaller::BuildWebApkProtoInBackground, |
| 173 shortcut_info, SkBitmap(), stale_manifest, |
| 174 icon_url_to_murmur2_hash_map), |
| 175 base::Bind(&WebApkInstallerRunner::OnBuiltWebApkProto, |
| 176 base::Unretained(this))); |
| 177 |
| 178 Run(); |
| 179 } |
| 180 |
| 157 void Run() { | 181 void Run() { |
| 158 base::RunLoop run_loop; | 182 base::RunLoop run_loop; |
| 159 on_completed_callback_ = run_loop.QuitClosure(); | 183 on_completed_callback_ = run_loop.QuitClosure(); |
| 160 run_loop.Run(); | 184 run_loop.Run(); |
| 161 } | 185 } |
| 162 | 186 |
| 163 bool success() { return success_; } | 187 bool success() { return success_; } |
| 164 | 188 |
| 189 webapk::WebApk* GetWebApkRequest() { return webapk_request_.get(); } |
| 190 |
| 165 private: | 191 private: |
| 166 void OnCompleted(bool success, const std::string& webapk_package) { | 192 void OnCompleted(bool success, const std::string& webapk_package) { |
| 167 success_ = success; | 193 success_ = success; |
| 168 on_completed_callback_.Run(); | 194 on_completed_callback_.Run(); |
| 169 } | 195 } |
| 170 | 196 |
| 197 scoped_refptr<base::TaskRunner> GetBackgroundTaskRunner() { |
| 198 return content::BrowserThread::GetBlockingPool() |
| 199 ->GetTaskRunnerWithShutdownBehavior( |
| 200 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); |
| 201 } |
| 202 |
| 203 // Called when the |webapk| request is populated. |
| 204 void OnBuiltWebApkProto(std::unique_ptr<webapk::WebApk> webapk) { |
| 205 webapk_request_ = std::move(webapk); |
| 206 on_completed_callback_.Run(); |
| 207 } |
| 208 |
| 171 scoped_refptr<net::TestURLRequestContextGetter> | 209 scoped_refptr<net::TestURLRequestContextGetter> |
| 172 url_request_context_getter_; | 210 url_request_context_getter_; |
| 173 | 211 |
| 174 // The Web Manifest's icon URL. | 212 // The Web Manifest's icon URL. |
| 175 const GURL best_icon_url_; | 213 const GURL best_icon_url_; |
| 176 | 214 |
| 177 // Called after the installation process has succeeded or failed. | 215 // Called after the installation process has succeeded or failed. |
| 178 base::Closure on_completed_callback_; | 216 base::Closure on_completed_callback_; |
| 179 | 217 |
| 180 // Whether the installation process succeeded. | 218 // Whether the installation process succeeded. |
| 181 bool success_; | 219 bool success_; |
| 182 | 220 |
| 183 // Whether the Google Play install delegate is available. | 221 // Whether the Google Play install delegate is available. |
| 184 bool has_google_play_webapk_install_delegate_; | 222 bool has_google_play_webapk_install_delegate_; |
| 185 | 223 |
| 224 // The populated webapk::WebApk. |
| 225 std::unique_ptr<webapk::WebApk> webapk_request_; |
| 226 |
| 186 DISALLOW_COPY_AND_ASSIGN(WebApkInstallerRunner); | 227 DISALLOW_COPY_AND_ASSIGN(WebApkInstallerRunner); |
| 187 }; | 228 }; |
| 188 | 229 |
| 189 // Builds a webapk::WebApkResponse with |download_url| as the WebAPK download | 230 // Builds a webapk::WebApkResponse with |download_url| as the WebAPK download |
| 190 // URL. | 231 // URL. |
| 191 std::unique_ptr<net::test_server::HttpResponse> BuildValidWebApkResponse( | 232 std::unique_ptr<net::test_server::HttpResponse> BuildValidWebApkResponse( |
| 192 const GURL& download_url) { | 233 const GURL& download_url) { |
| 193 std::unique_ptr<webapk::WebApkResponse> response_proto( | 234 std::unique_ptr<webapk::WebApkResponse> response_proto( |
| 194 new webapk::WebApkResponse); | 235 new webapk::WebApkResponse); |
| 195 response_proto->set_package_name(kDownloadedWebApkPackageName); | 236 response_proto->set_package_name(kDownloadedWebApkPackageName); |
| 196 response_proto->set_signed_download_url(download_url.spec()); | 237 response_proto->set_signed_download_url(download_url.spec()); |
| 197 std::string response_content; | 238 std::string response_content; |
| 198 response_proto->SerializeToString(&response_content); | 239 response_proto->SerializeToString(&response_content); |
| 199 | 240 |
| 200 std::unique_ptr<net::test_server::BasicHttpResponse> response( | 241 std::unique_ptr<net::test_server::BasicHttpResponse> response( |
| 201 new net::test_server::BasicHttpResponse()); | 242 new net::test_server::BasicHttpResponse()); |
| 202 response->set_code(net::HTTP_OK); | 243 response->set_code(net::HTTP_OK); |
| 203 response->set_content(response_content); | 244 response->set_content(response_content); |
| 204 return std::move(response); | 245 return std::move(response); |
| 205 } | 246 } |
| 206 | 247 |
| 207 } // anonymous namespace | |
| 208 | 248 |
| 209 class WebApkInstallerTest : public ::testing::Test { | 249 class WebApkInstallerTest : public ::testing::Test { |
| 210 public: | 250 public: |
| 211 typedef base::Callback<std::unique_ptr<net::test_server::HttpResponse>(void)> | 251 typedef base::Callback<std::unique_ptr<net::test_server::HttpResponse>(void)> |
| 212 WebApkResponseBuilder; | 252 WebApkResponseBuilder; |
| 213 | 253 |
| 214 WebApkInstallerTest() | 254 WebApkInstallerTest() |
| 215 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {} | 255 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {} |
| 216 ~WebApkInstallerTest() override {} | 256 ~WebApkInstallerTest() override {} |
| 217 | 257 |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 EXPECT_TRUE(runner->success()); | 401 EXPECT_TRUE(runner->success()); |
| 362 } | 402 } |
| 363 | 403 |
| 364 // Test installation succeeds using Google Play. | 404 // Test installation succeeds using Google Play. |
| 365 TEST_F(WebApkInstallerTest, InstallFromGooglePlaySuccess) { | 405 TEST_F(WebApkInstallerTest, InstallFromGooglePlaySuccess) { |
| 366 std::unique_ptr<WebApkInstallerRunner> runner = CreateWebApkInstallerRunner(); | 406 std::unique_ptr<WebApkInstallerRunner> runner = CreateWebApkInstallerRunner(); |
| 367 runner->SetHasGooglePlayWebApkInstallDelegate(true); | 407 runner->SetHasGooglePlayWebApkInstallDelegate(true); |
| 368 runner->RunInstallWebApk(); | 408 runner->RunInstallWebApk(); |
| 369 EXPECT_TRUE(runner->success()); | 409 EXPECT_TRUE(runner->success()); |
| 370 } | 410 } |
| 411 |
| 412 // When there is no Web Manifest available for a site, an empty |best_icon_url| |
| 413 // is used to build a WebApk update request. Tests the request can be built |
| 414 // properly. |
| 415 TEST_F(WebApkInstallerTest, BuildWebApkProtoWhenManifestIsObsolete) { |
| 416 GURL icon_url_1 = test_server()->GetURL("/icon1.png"); |
| 417 GURL icon_url_2 = test_server()->GetURL("/icon2.png"); |
| 418 std::string icon_murmur2_hash_1 = "1"; |
| 419 std::string icon_murmur2_hash_2 = "2"; |
| 420 std::map<std::string, std::string> icon_url_to_murmur2_hash_map; |
| 421 icon_url_to_murmur2_hash_map[icon_url_1.spec()] = icon_murmur2_hash_1; |
| 422 icon_url_to_murmur2_hash_map[icon_url_2.spec()] = icon_murmur2_hash_2; |
| 423 |
| 424 std::unique_ptr<WebApkInstallerRunner> runner = CreateWebApkInstallerRunner(); |
| 425 runner->BuildWebApkProto(GURL(""), true, icon_url_to_murmur2_hash_map); |
| 426 webapk::WebApk* webapk_request = runner->GetWebApkRequest(); |
| 427 EXPECT_NE(nullptr, webapk_request); |
| 428 |
| 429 webapk::WebAppManifest manifest = webapk_request->manifest(); |
| 430 EXPECT_EQ(3, manifest.icons_size()); |
| 431 |
| 432 webapk::Image icons[3]; |
| 433 for (int i = 0; i < 3; ++i) |
| 434 icons[i] = manifest.icons(i); |
| 435 |
| 436 EXPECT_EQ("", icons[0].src()); |
| 437 EXPECT_FALSE(icons[0].has_hash()); |
| 438 EXPECT_TRUE(icons[0].has_image_data()); |
| 439 |
| 440 EXPECT_EQ(icon_url_1.spec(), icons[1].src()); |
| 441 EXPECT_EQ(icon_murmur2_hash_1, icons[1].hash()); |
| 442 EXPECT_FALSE(icons[1].has_image_data()); |
| 443 |
| 444 EXPECT_EQ(icon_url_2.spec(), icons[2].src()); |
| 445 EXPECT_EQ(icon_murmur2_hash_2, icons[2].hash()); |
| 446 EXPECT_FALSE(icons[2].has_image_data()); |
| 447 } |
| 448 |
| 449 // Tests a WebApk install or update request is built properly when the Chrome |
| 450 // knows the best icon URL of a site after fetching its Web Manifest. |
| 451 TEST_F(WebApkInstallerTest, BuildWebApkProtoWhenManifestIsAvailable) { |
| 452 GURL icon_url_1 = test_server()->GetURL("/icon.png"); |
| 453 GURL best_icon_url = test_server()->GetURL(kBestIconUrl); |
| 454 std::string icon_murmur2_hash_1 = "1"; |
| 455 std::string best_icon_murmur2_hash = "0"; |
| 456 std::map<std::string, std::string> icon_url_to_murmur2_hash_map; |
| 457 icon_url_to_murmur2_hash_map[icon_url_1.spec()] = icon_murmur2_hash_1; |
| 458 icon_url_to_murmur2_hash_map[best_icon_url.spec()] = |
| 459 best_icon_murmur2_hash; |
| 460 |
| 461 std::unique_ptr<WebApkInstallerRunner> runner = CreateWebApkInstallerRunner(); |
| 462 runner->BuildWebApkProto(best_icon_url, false, icon_url_to_murmur2_hash_map); |
| 463 webapk::WebApk* webapk_request = runner->GetWebApkRequest(); |
| 464 EXPECT_NE(nullptr, webapk_request); |
| 465 |
| 466 webapk::WebAppManifest manifest = webapk_request->manifest(); |
| 467 EXPECT_EQ(2, manifest.icons_size()); |
| 468 |
| 469 webapk::Image icons[2]; |
| 470 for (int i = 0; i < 2; ++i) |
| 471 icons[i] = manifest.icons(i); |
| 472 |
| 473 EXPECT_EQ(best_icon_url.spec(), icons[0].src()); |
| 474 EXPECT_EQ(best_icon_murmur2_hash, icons[0].hash()); |
| 475 EXPECT_TRUE(icons[0].has_image_data()); |
| 476 |
| 477 EXPECT_EQ(icon_url_1.spec(), icons[1].src()); |
| 478 EXPECT_EQ(icon_murmur2_hash_1, icons[1].hash()); |
| 479 EXPECT_FALSE(icons[1].has_image_data()); |
| 480 } |
| OLD | NEW |