Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(396)

Side by Side Diff: chrome/browser/android/webapps/add_to_homescreen_data_fetcher_unittest.cc

Issue 2960103002: Improve add to homescreen data fetcher unit tests. (Closed)
Patch Set: Comments Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/browser/installable/installable_manager.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/webapps/add_to_homescreen_data_fetcher.h" 5 #include "chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <string> 8 #include <string>
9 #include <utility>
9 10
10 #include "base/callback_forward.h" 11 #include "base/bind.h"
11 #include "base/files/file_path.h" 12 #include "base/callback.h"
12 #include "base/macros.h" 13 #include "base/macros.h"
13 #include "base/memory/ref_counted.h" 14 #include "base/memory/ref_counted.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/run_loop.h" 15 #include "base/run_loop.h"
16 #include "base/strings/nullable_string16.h" 16 #include "base/strings/nullable_string16.h"
17 #include "base/strings/string_util.h" 17 #include "base/strings/string_util.h"
18 #include "base/strings/utf_string_conversions.h" 18 #include "base/strings/utf_string_conversions.h"
19 #include "base/time/time.h"
20 #include "chrome/browser/installable/installable_manager.h" 19 #include "chrome/browser/installable/installable_manager.h"
21 #include "chrome/common/web_application_info.h" 20 #include "chrome/common/web_application_info.h"
22 #include "chrome/test/base/chrome_render_view_host_test_harness.h" 21 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
23 #include "chrome/test/base/testing_profile.h" 22 #include "chrome/test/base/testing_profile.h"
24 #include "content/browser/service_worker/embedded_worker_test_helper.h"
25 #include "content/browser/service_worker/service_worker_context_core.h"
26 #include "content/common/service_worker/service_worker_status_code.h"
27 #include "content/public/browser/browser_thread.h"
28 #include "content/public/browser/site_instance.h"
29 #include "content/public/browser/web_contents.h" 23 #include "content/public/browser/web_contents.h"
30 #include "content/public/common/manifest.h" 24 #include "content/public/common/manifest.h"
31 #include "content/test/test_web_contents.h"
32 #include "net/http/http_status_code.h"
33 #include "third_party/WebKit/public/platform/WebDisplayMode.h" 25 #include "third_party/WebKit/public/platform/WebDisplayMode.h"
34 #include "ui/gfx/image/image_unittest_util.h" 26 #include "ui/gfx/image/image_unittest_util.h"
35 #include "url/gurl.h" 27 #include "url/gurl.h"
36 28
37 namespace { 29 namespace {
38 30
39 const char* kWebApplicationInfoTitle = "Meta Title"; 31 const char* kWebApplicationInfoTitle = "Meta Title";
40 const char* kDefaultManifestUrl = "https://www.example.com/manifest.json"; 32 const char* kDefaultManifestUrl = "https://www.example.com/manifest.json";
33 const char* kDefaultIconUrl = "https://www.example.com/icon.png";
41 const char* kDefaultManifestName = "Default Name"; 34 const char* kDefaultManifestName = "Default Name";
42 const char* kDefaultManifestShortName = "Default Short Name"; 35 const char* kDefaultManifestShortName = "Default Short Name";
43 const char* kDefaultStartUrl = "https://www.example.com/index.html"; 36 const char* kDefaultStartUrl = "https://www.example.com/index.html";
44 const blink::WebDisplayMode kDefaultManifestDisplayMode = 37 const blink::WebDisplayMode kDefaultManifestDisplayMode =
45 blink::kWebDisplayModeStandalone; 38 blink::kWebDisplayModeStandalone;
39 const int kIconSizePx = 144;
46 40
47 // WebContents subclass which mocks out image and manifest fetching. 41 // Tracks which of the AddToHomescreenDataFetcher::Observer methods have been
48 class MockWebContents : public content::TestWebContents {
49 public:
50 explicit MockWebContents(content::BrowserContext* browser_context)
51 : content::TestWebContents(browser_context),
52 should_image_time_out_(false),
53 should_manifest_time_out_(false) {}
54
55 ~MockWebContents() override {}
56
57 void SetManifest(const GURL& manifest_url,
58 const content::Manifest& manifest) {
59 manifest_url_ = manifest_url;
60 manifest_ = manifest;
61 }
62
63 int DownloadImage(const GURL& url,
64 bool is_favicon,
65 uint32_t max_bitmap_size,
66 bool bypass_cache,
67 const ImageDownloadCallback& callback) override {
68 if (should_image_time_out_)
69 return 0;
70
71 const int kIconSizePx = 144;
72 SkBitmap icon = gfx::test::CreateBitmap(kIconSizePx, kIconSizePx);
73 std::vector<SkBitmap> icons(1u, icon);
74 std::vector<gfx::Size> pixel_sizes(1u, gfx::Size(kIconSizePx, kIconSizePx));
75 content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI)
76 ->PostTask(FROM_HERE, base::Bind(callback, 0, net::HTTP_OK, url, icons,
77 pixel_sizes));
78 return 0;
79 }
80
81 void GetManifest(const GetManifestCallback& callback) override {
82 if (should_manifest_time_out_)
83 return;
84
85 content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI)
86 ->PostTask(FROM_HERE, base::Bind(callback, manifest_url_, manifest_));
87 }
88
89 void SetShouldImageTimeOut(bool should_time_out) {
90 should_image_time_out_ = should_time_out;
91 }
92
93 void SetShouldManifestTimeOut(bool should_time_out) {
94 should_manifest_time_out_ = should_time_out;
95 }
96
97 private:
98 GURL manifest_url_;
99 content::Manifest manifest_;
100 bool should_image_time_out_;
101 bool should_manifest_time_out_;
102
103 DISALLOW_COPY_AND_ASSIGN(MockWebContents);
104 };
105
106 // Tracks which of the AddToHomescreenDataFetcher::Observer callbacks have been
107 // called. 42 // called.
108 class ObserverWaiter : public AddToHomescreenDataFetcher::Observer { 43 class ObserverWaiter : public AddToHomescreenDataFetcher::Observer {
109 public: 44 public:
110 ObserverWaiter() 45 ObserverWaiter()
111 : is_webapk_compatible_(false), 46 : is_webapk_compatible_(false),
112 determined_webapk_compatibility_(false), 47 determined_webapk_compatibility_(false),
113 title_available_(false), 48 title_available_(false),
114 data_available_(false) {} 49 data_available_(false) {}
115 ~ObserverWaiter() override {} 50 ~ObserverWaiter() override {}
116 51
117 // Waits till the OnDataAvailable() callback is called. 52 // Waits till the OnDataAvailable() callback is called.
118 void WaitForDataAvailable() { 53 void WaitForDataAvailable() {
119 if (data_available_) 54 if (data_available_)
120 return; 55 return;
121 56
122 base::RunLoop run_loop; 57 base::RunLoop run_loop;
123 quit_closure_ = run_loop.QuitClosure(); 58 quit_closure_ = run_loop.QuitClosure();
124 run_loop.Run(); 59 run_loop.Run();
125 } 60 }
126 61
127 void OnDidDetermineWebApkCompatibility(bool is_webapk_compatible) override { 62 void OnDidDetermineWebApkCompatibility(bool is_webapk_compatible) override {
63 // This should only be called once.
64 EXPECT_FALSE(determined_webapk_compatibility_);
128 EXPECT_FALSE(title_available_); 65 EXPECT_FALSE(title_available_);
129 determined_webapk_compatibility_ = true; 66 determined_webapk_compatibility_ = true;
130 is_webapk_compatible_ = is_webapk_compatible; 67 is_webapk_compatible_ = is_webapk_compatible;
131 } 68 }
132 69
133 void OnUserTitleAvailable(const base::string16& title) override { 70 void OnUserTitleAvailable(const base::string16& title) override {
71 // This should only be called once.
72 EXPECT_FALSE(title_available_);
134 EXPECT_FALSE(data_available_); 73 EXPECT_FALSE(data_available_);
135 title_available_ = true; 74 title_available_ = true;
136 title_ = title; 75 title_ = title;
137 } 76 }
138 77
139 SkBitmap FinalizeLauncherIconInBackground(const SkBitmap& icon, 78 SkBitmap FinalizeLauncherIconInBackground(const SkBitmap& icon,
140 const GURL& url, 79 const GURL& url,
141 bool* is_generated) override { 80 bool* is_generated) override {
142 *is_generated = false; 81 *is_generated = false;
143 return icon; 82 return icon;
144 } 83 }
145 84
146 void OnDataAvailable(const ShortcutInfo& info, 85 void OnDataAvailable(const ShortcutInfo& info,
147 const SkBitmap& primary_icon, 86 const SkBitmap& primary_icon,
148 const SkBitmap& badge_icon) override { 87 const SkBitmap& badge_icon) override {
88 // This should only be called once.
89 EXPECT_FALSE(data_available_);
149 EXPECT_TRUE(title_available_); 90 EXPECT_TRUE(title_available_);
150 data_available_ = true; 91 data_available_ = true;
151 if (!quit_closure_.is_null()) 92 if (!quit_closure_.is_null())
152 quit_closure_.Run(); 93 quit_closure_.Run();
153 } 94 }
154 95
155 base::string16 title() const { return title_; } 96 base::string16 title() const { return title_; }
156 bool is_webapk_compatible() const { return is_webapk_compatible_; } 97 bool is_webapk_compatible() const { return is_webapk_compatible_; }
157 bool determined_webapk_compatibility() const { 98 bool determined_webapk_compatibility() const {
158 return determined_webapk_compatibility_; 99 return determined_webapk_compatibility_;
159 } 100 }
160 bool title_available() const { return title_available_; } 101 bool title_available() const { return title_available_; }
161 102
162 private: 103 private:
163 base::string16 title_; 104 base::string16 title_;
164 bool is_webapk_compatible_; 105 bool is_webapk_compatible_;
165 bool determined_webapk_compatibility_; 106 bool determined_webapk_compatibility_;
166 bool title_available_; 107 bool title_available_;
167 bool data_available_; 108 bool data_available_;
168 base::Closure quit_closure_; 109 base::Closure quit_closure_;
169 110
170 DISALLOW_COPY_AND_ASSIGN(ObserverWaiter); 111 DISALLOW_COPY_AND_ASSIGN(ObserverWaiter);
171 }; 112 };
172 113
173 // Builds non-null base::NullableString16 from a UTF8 string. 114 // Builds non-null base::NullableString16 from a UTF8 string.
174 base::NullableString16 NullableStringFromUTF8(const std::string& value) { 115 base::NullableString16 NullableStringFromUTF8(const std::string& value) {
175 return base::NullableString16(base::UTF8ToUTF16(value), false); 116 return base::NullableString16(base::UTF8ToUTF16(value), false);
176 } 117 }
177 118
178 content::Manifest BuildEmptyManifest() {
179 return content::Manifest();
180 }
181
182 // Builds WebAPK compatible content::Manifest. 119 // Builds WebAPK compatible content::Manifest.
183 content::Manifest BuildDefaultManifest() { 120 content::Manifest BuildDefaultManifest() {
184 content::Manifest manifest; 121 content::Manifest manifest;
185 manifest.name = NullableStringFromUTF8(kDefaultManifestName); 122 manifest.name = NullableStringFromUTF8(kDefaultManifestName);
186 manifest.short_name = NullableStringFromUTF8(kDefaultManifestShortName); 123 manifest.short_name = NullableStringFromUTF8(kDefaultManifestShortName);
187 manifest.start_url = GURL(kDefaultStartUrl); 124 manifest.start_url = GURL(kDefaultStartUrl);
188 manifest.display = kDefaultManifestDisplayMode; 125 manifest.display = kDefaultManifestDisplayMode;
189 126
190 content::Manifest::Icon primary_icon; 127 content::Manifest::Icon primary_icon;
191 primary_icon.type = base::ASCIIToUTF16("image/png"); 128 primary_icon.type = base::ASCIIToUTF16("image/png");
192 primary_icon.sizes.push_back(gfx::Size(144, 144)); 129 primary_icon.sizes.push_back(gfx::Size(144, 144));
193 primary_icon.purpose.push_back(content::Manifest::Icon::IconPurpose::ANY); 130 primary_icon.purpose.push_back(content::Manifest::Icon::IconPurpose::ANY);
194 primary_icon.src = GURL("https://www.google.com/image.png"); 131 primary_icon.src = GURL(kDefaultIconUrl);
195 manifest.icons.push_back(primary_icon); 132 manifest.icons.push_back(primary_icon);
196 133
197 return manifest; 134 return manifest;
198 } 135 }
199 136
200 } // anonymous namespace 137 } // anonymous namespace
201 138
139 class TestInstallableManager : public InstallableManager {
140 public:
141 explicit TestInstallableManager(content::WebContents* web_contents)
142 : InstallableManager(web_contents) {}
143
144 void GetData(const InstallableParams& params,
145 const InstallableCallback& callback) override {
146 InstallableStatusCode code = code_;
147 if (params.check_installable) {
148 if (!IsManifestValidForWebApp(manifest_))
149 code = valid_manifest_->error;
150 else if (!is_installable_)
151 code = NOT_OFFLINE_CAPABLE;
152 }
153
154 // Store the callback so it can be redispatched later.
155 InstallableData data{
156 code,
157 GURL(kDefaultManifestUrl),
158 manifest_,
159 params.fetch_valid_primary_icon ? primary_icon_url_ : GURL(),
160 params.fetch_valid_primary_icon ? primary_icon_.get() : nullptr,
161 params.fetch_valid_badge_icon ? badge_icon_url_ : GURL(),
162 params.fetch_valid_badge_icon ? badge_icon_.get() : nullptr,
163 params.check_installable ? is_installable_ : false};
164 callback_ = base::BindOnce(callback, data);
165
166 if (should_manifest_time_out_ ||
167 (params.check_installable && should_installable_time_out_)) {
168 return;
169 }
170
171 std::move(callback_).Run();
172 }
173
174 bool IsDeferredCallbackNull() { return callback_.is_null(); }
175
176 void RunCallback() {
177 EXPECT_FALSE(IsDeferredCallbackNull());
178 std::move(callback_).Run();
179 base::RunLoop().RunUntilIdle();
180 }
181
182 void SetInstallable(bool is_installable) { is_installable_ = is_installable; }
183
184 void SetManifest(const content::Manifest& manifest) {
185 manifest_ = manifest;
186
187 if (manifest.icons.empty()) {
188 code_ = NO_ACCEPTABLE_ICON;
189 is_installable_ = false;
190 } else {
191 primary_icon_url_ = manifest_.icons[0].src;
192 primary_icon_.reset(
193 new SkBitmap(gfx::test::CreateBitmap(kIconSizePx, kIconSizePx)));
194
195 badge_icon_url_ = manifest_.icons[0].src;
196 badge_icon_.reset(
197 new SkBitmap(gfx::test::CreateBitmap(kIconSizePx, kIconSizePx)));
198 code_ = NO_ERROR_DETECTED;
199 is_installable_ = true;
200 }
201 }
202
203 void SetShouldManifestTimeOut(bool should_time_out) {
204 should_manifest_time_out_ = should_time_out;
205 }
206
207 void SetShouldInstallableTimeOut(bool should_time_out) {
208 should_installable_time_out_ = should_time_out;
209 }
210
211 private:
212 base::OnceClosure callback_;
213 InstallableStatusCode code_;
214 content::Manifest manifest_;
215 GURL primary_icon_url_;
216 GURL badge_icon_url_;
217 std::unique_ptr<SkBitmap> primary_icon_;
218 std::unique_ptr<SkBitmap> badge_icon_;
219
220 bool is_installable_ = false;
221
222 bool should_manifest_time_out_ = false;
223 bool should_installable_time_out_ = false;
224 };
225
202 // Tests AddToHomescreenDataFetcher. These tests should be browser tests but 226 // Tests AddToHomescreenDataFetcher. These tests should be browser tests but
203 // Android does not support browser tests yet (crbug.com/611756). 227 // Android does not support browser tests yet (crbug.com/611756).
204 class AddToHomescreenDataFetcherTest : public ChromeRenderViewHostTestHarness { 228 class AddToHomescreenDataFetcherTest : public ChromeRenderViewHostTestHarness {
205 public: 229 public:
206 AddToHomescreenDataFetcherTest() {} 230 AddToHomescreenDataFetcherTest() {}
207 ~AddToHomescreenDataFetcherTest() override {} 231 ~AddToHomescreenDataFetcherTest() override {}
208 232
209 void SetUp() override { 233 void SetUp() override {
210 ChromeRenderViewHostTestHarness::SetUp(); 234 ChromeRenderViewHostTestHarness::SetUp();
211 235
212 ASSERT_TRUE(profile()->CreateHistoryService(false, true)); 236 ASSERT_TRUE(profile()->CreateHistoryService(false, true));
213 profile()->CreateFaviconService(); 237 profile()->CreateFaviconService();
214 238
215 embedded_worker_test_helper_.reset( 239 // Manually inject the TestInstallableManager as a "InstallableManager"
216 new content::EmbeddedWorkerTestHelper(base::FilePath())); 240 // WebContentsUserData. We can't directly call ::CreateForWebContents due to
217 241 // typing issues since TestInstallableManager doesn't directly inherit from
218 scoped_refptr<content::SiteInstance> site_instance = 242 // WebContentsUserData.
219 content::SiteInstance::Create(browser_context()); 243 web_contents()->SetUserData(
220 site_instance->GetProcess()->Init(); 244 TestInstallableManager::UserDataKey(),
221 MockWebContents* mock_web_contents = new MockWebContents(browser_context()); 245 base::WrapUnique(new TestInstallableManager(web_contents())));
222 mock_web_contents->Init(content::WebContents::CreateParams( 246 installable_manager_ = static_cast<TestInstallableManager*>(
223 browser_context(), std::move(site_instance))); 247 web_contents()->GetUserData(TestInstallableManager::UserDataKey()));
224 InstallableManager::CreateForWebContents(mock_web_contents);
225 SetContents(mock_web_contents);
226 NavigateAndCommit(GURL(kDefaultStartUrl));
227 }
228
229 void TearDown() override {
230 embedded_worker_test_helper_.reset();
231 ChromeRenderViewHostTestHarness::TearDown();
232 } 248 }
233 249
234 scoped_refptr<AddToHomescreenDataFetcher> BuildFetcher( 250 scoped_refptr<AddToHomescreenDataFetcher> BuildFetcher(
235 bool check_webapk_compatible, 251 bool check_webapk_compatible,
236 AddToHomescreenDataFetcher::Observer* observer) { 252 AddToHomescreenDataFetcher::Observer* observer) {
237 return new AddToHomescreenDataFetcher(web_contents(), 1, 1, 1, 1, 1, 500, 253 return new AddToHomescreenDataFetcher(web_contents(), 1, 1, 1, 1, 1, 500,
238 check_webapk_compatible, observer); 254 check_webapk_compatible, observer);
239 } 255 }
240 256
241 // Set the manifest to be returned as a result of WebContents::GetManifest(). 257 void RunFetcher(scoped_refptr<AddToHomescreenDataFetcher> fetcher,
242 void SetManifest(const GURL& manifest_url, 258 ObserverWaiter& waiter,
243 const content::Manifest& manifest) { 259 const char* expected_title,
244 MockWebContents* mock_web_contents = 260 blink::WebDisplayMode display_mode,
245 static_cast<MockWebContents*>(web_contents()); 261 bool is_webapk_compatible) {
246 mock_web_contents->SetManifest(manifest_url, manifest); 262 WebApplicationInfo web_application_info;
263 web_application_info.title = base::UTF8ToUTF16(kWebApplicationInfoTitle);
264
265 fetcher->OnDidGetWebApplicationInfo(web_application_info);
266 waiter.WaitForDataAvailable();
267
268 EXPECT_EQ(check_webapk_compatibility(),
269 waiter.determined_webapk_compatibility());
270 EXPECT_EQ(is_webapk_compatible, waiter.is_webapk_compatible());
271 EXPECT_TRUE(waiter.title_available());
272 EXPECT_TRUE(base::EqualsASCII(waiter.title(), expected_title));
273 EXPECT_TRUE(
274 base::EqualsASCII(fetcher->shortcut_info().user_title, expected_title));
275 EXPECT_EQ(display_mode, fetcher->shortcut_info().display);
247 } 276 }
248 277
249 void SetShouldImageTimeOut(bool should_time_out) { 278 void SetManifest(const content::Manifest& manifest) {
250 MockWebContents* mock_web_contents = 279 installable_manager_->SetManifest(manifest);
251 static_cast<MockWebContents*>(web_contents()); 280 }
252 mock_web_contents->SetShouldImageTimeOut(should_time_out); 281
282 void SetInstallable(bool is_installable) {
283 installable_manager_->SetInstallable(is_installable);
253 } 284 }
254 285
255 void SetShouldManifestTimeOut(bool should_time_out) { 286 void SetShouldManifestTimeOut(bool should_time_out) {
256 MockWebContents* mock_web_contents = 287 installable_manager_->SetShouldManifestTimeOut(should_time_out);
257 static_cast<MockWebContents*>(web_contents());
258 mock_web_contents->SetShouldManifestTimeOut(should_time_out);
259 } 288 }
260 289
261 // Registers service worker at |url|. Blocks till the service worker is 290 void SetShouldInstallableTimeOut(bool should_time_out) {
262 // registered. 291 installable_manager_->SetShouldInstallableTimeOut(should_time_out);
263 void RegisterServiceWorker(const GURL& url) {
264 base::RunLoop run_loop;
265 embedded_worker_test_helper_->context()->RegisterServiceWorker(
266 url, GURL(url.spec() + "/service_worker.js"), nullptr,
267 base::Bind(&AddToHomescreenDataFetcherTest::OnServiceWorkerRegistered,
268 base::Unretained(this), run_loop.QuitClosure()));
269 } 292 }
270 293
271 private: 294 void RunDeferredCallback() { installable_manager_->RunCallback(); }
272 // Callback for RegisterServiceWorker() for when service worker registration 295
273 // has completed. 296 bool IsDeferredCallbackNull() {
274 void OnServiceWorkerRegistered(const base::Closure& callback, 297 return installable_manager_->IsDeferredCallbackNull();
275 content::ServiceWorkerStatusCode status,
276 const std::string& status_message,
277 int64_t registration_id) {
278 ASSERT_EQ(content::SERVICE_WORKER_OK, status)
279 << content::ServiceWorkerStatusToString(status);
280 callback.Run();
281 } 298 }
282 299
283 std::unique_ptr<content::EmbeddedWorkerTestHelper> 300 virtual bool check_webapk_compatibility() { return true; }
284 embedded_worker_test_helper_; 301
302 private:
303 TestInstallableManager* installable_manager_;
285 304
286 DISALLOW_COPY_AND_ASSIGN(AddToHomescreenDataFetcherTest); 305 DISALLOW_COPY_AND_ASSIGN(AddToHomescreenDataFetcherTest);
287 }; 306 };
288 307
289 // Class for tests which should be run with AddToHomescreenDataFetcher built 308 // Class for tests which should be run with AddToHomescreenDataFetcher built
290 // with both true and false values of |check_webapk_compatible|. 309 // with both true and false values of |check_webapk_compatible|.
291 class AddToHomescreenDataFetcherTestCommon 310 class AddToHomescreenDataFetcherTestCommon
292 : public AddToHomescreenDataFetcherTest, 311 : public AddToHomescreenDataFetcherTest,
293 public testing::WithParamInterface<bool> { 312 public testing::WithParamInterface<bool> {
294 public: 313 public:
295 AddToHomescreenDataFetcherTestCommon() {} 314 AddToHomescreenDataFetcherTestCommon() {}
296 ~AddToHomescreenDataFetcherTestCommon() override {} 315 ~AddToHomescreenDataFetcherTestCommon() override {}
297 316
298 scoped_refptr<AddToHomescreenDataFetcher> BuildFetcher( 317 scoped_refptr<AddToHomescreenDataFetcher> BuildFetcher(
299 AddToHomescreenDataFetcher::Observer* observer) { 318 AddToHomescreenDataFetcher::Observer* observer) {
300 return AddToHomescreenDataFetcherTest::BuildFetcher( 319 return AddToHomescreenDataFetcherTest::BuildFetcher(
301 check_webapk_compatibility(), observer); 320 check_webapk_compatibility(), observer);
302 } 321 }
303 322
304 // The value of |check_webapk_compatible| used when building the 323 // The value of |check_webapk_compatible| used when building the
305 // AddToHomescreenDataFetcher. 324 // AddToHomescreenDataFetcher.
306 bool check_webapk_compatibility() { return GetParam(); } 325 bool check_webapk_compatibility() override { return GetParam(); }
307 326
308 private: 327 private:
309 DISALLOW_COPY_AND_ASSIGN(AddToHomescreenDataFetcherTestCommon); 328 DISALLOW_COPY_AND_ASSIGN(AddToHomescreenDataFetcherTestCommon);
310 }; 329 };
311 330
312 // Checks that AddToHomescreenDataFetcher::Observer::OnUserTitleAvailable() is
313 // called when the web manifest returned is empty. The add-to-homescreen dialog
314 // makes the dialog's text field editable once OnUserTitleAvailable() is called.
315 TEST_P(AddToHomescreenDataFetcherTestCommon, EmptyManifest) { 331 TEST_P(AddToHomescreenDataFetcherTestCommon, EmptyManifest) {
316 WebApplicationInfo web_application_info; 332 // Check that an empty manifest has the appropriate methods run.
317 web_application_info.title = base::UTF8ToUTF16(kWebApplicationInfoTitle); 333 ObserverWaiter waiter;
318 334 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter));
319 SetManifest(GURL(kDefaultManifestUrl), BuildEmptyManifest()); 335 RunFetcher(fetcher, waiter, kWebApplicationInfoTitle,
320 336 blink::kWebDisplayModeBrowser, false);
321 ObserverWaiter waiter; 337 EXPECT_TRUE(IsDeferredCallbackNull());
322 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter)); 338 fetcher->set_weak_observer(nullptr);
323 fetcher->OnDidGetWebApplicationInfo(web_application_info); 339 }
324 waiter.WaitForDataAvailable(); 340
325 341 TEST_P(AddToHomescreenDataFetcherTestCommon, NoIconManifest) {
342 // Test a manifest with no icons. This should use the metadata title and have
343 // an empty icon in this test runner (in production the empty icon would be
344 // replaced by a favicon or a generated icon).
345 content::Manifest manifest = BuildDefaultManifest();
346 manifest.icons.clear();
347 SetManifest(manifest);
348
349 ObserverWaiter waiter;
350 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter));
351 RunFetcher(fetcher, waiter, kDefaultManifestShortName,
352 blink::kWebDisplayModeStandalone, false);
353 EXPECT_TRUE(IsDeferredCallbackNull());
354
355 EXPECT_TRUE(fetcher->primary_icon().drawsNothing());
356 EXPECT_TRUE(fetcher->shortcut_info().best_primary_icon_url.is_empty());
357 EXPECT_TRUE(fetcher->badge_icon().drawsNothing());
358 EXPECT_TRUE(fetcher->shortcut_info().best_badge_icon_url.is_empty());
359
360 fetcher->set_weak_observer(nullptr);
361 }
362
363 TEST_P(AddToHomescreenDataFetcherTestCommon, ManifestFetchTimesOut) {
364 // Check that the AddToHomescreenDataFetcher::Observer methods are called
365 // if the first call to InstallableManager::GetData() times out. This should
366 // fall back to the metadata title and have an empty icon.
367 SetShouldManifestTimeOut(true);
368
369 {
370 // Check a site with no service worker.
371 SetManifest(BuildDefaultManifest());
372 ObserverWaiter waiter;
373 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter));
374 RunFetcher(fetcher, waiter, kWebApplicationInfoTitle,
375 blink::kWebDisplayModeBrowser, false);
376
377 EXPECT_TRUE(fetcher->primary_icon().drawsNothing());
378 EXPECT_TRUE(fetcher->shortcut_info().best_primary_icon_url.is_empty());
379
380 // Ensure GetData() does not call any observer methods if it is dispatched
381 // after the timeout.
382 RunDeferredCallback();
383 fetcher->set_weak_observer(nullptr);
384 }
385
386 {
387 // Check with a service worker present.
388 SetManifest(BuildDefaultManifest());
389 ObserverWaiter waiter;
pkotwicz 2017/06/30 23:54:52 The setup here is identical to the setup on line 3
dominickn 2017/07/05 07:03:26 Done.
390 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter));
391 RunFetcher(fetcher, waiter, kWebApplicationInfoTitle,
392 blink::kWebDisplayModeBrowser, false);
393
394 EXPECT_TRUE(fetcher->primary_icon().drawsNothing());
395 EXPECT_TRUE(fetcher->shortcut_info().best_primary_icon_url.is_empty());
396
397 // Ensure GetData() does not call any observer methods if it is dispatched
398 // after the timeout.
399 RunDeferredCallback();
400 fetcher->set_weak_observer(nullptr);
401 }
402 }
403
404 TEST_F(AddToHomescreenDataFetcherTest, ServiceWorkerCheckTimesOut) {
405 {
406 // Check that the AddToHomescreenDataFetcher::Observer methods are called
407 // if the service worker check times out on a page that is installable (i.e.
408 // it's taken too long) .This should use the short_name and icon from the
pkotwicz 2017/06/30 23:54:52 Nit: ' .T' -> '. T'
dominickn 2017/07/05 07:03:26 Done.
409 // manifest, but not be WebAPK-compatible. Only relevant when checking
410 // WebAPK compatibility.
411 SetManifest(BuildDefaultManifest());
412 SetShouldInstallableTimeOut(true);
413
414 ObserverWaiter waiter;
415 scoped_refptr<AddToHomescreenDataFetcher> fetcher(
416 BuildFetcher(true, &waiter));
417 RunFetcher(fetcher, waiter, kDefaultManifestShortName,
418 blink::kWebDisplayModeStandalone, false);
419
420 EXPECT_FALSE(fetcher->primary_icon().drawsNothing());
421 EXPECT_EQ(fetcher->shortcut_info().best_primary_icon_url,
422 GURL(kDefaultIconUrl));
423
424 // Ensure GetData() does not call any observer methods if it is dispatched
425 // after the timeout.
426 RunDeferredCallback();
427 fetcher->set_weak_observer(nullptr);
428 }
429
430 {
431 // Check the case where the service worker check times out because the
432 // service worker doesn't exist. This is subtly different since the deferred
433 // callback will be run with a NO_ERROR_DETECTED result rather than
434 // NOT_OFFLINE_CAPABLE as above.
pkotwicz 2017/06/30 23:54:52 After giving the matter some thought, I don't thin
dominickn 2017/07/05 07:03:26 This test case is checking the case where we have
435 SetInstallable(false);
436 SetShouldInstallableTimeOut(true);
437
438 ObserverWaiter waiter;
439 scoped_refptr<AddToHomescreenDataFetcher> fetcher(
440 BuildFetcher(true, &waiter));
441 RunFetcher(fetcher, waiter, kDefaultManifestShortName,
442 blink::kWebDisplayModeStandalone, false);
443
444 EXPECT_FALSE(fetcher->primary_icon().drawsNothing());
445 EXPECT_EQ(fetcher->shortcut_info().best_primary_icon_url,
446 GURL(kDefaultIconUrl));
447
448 // Ensure GetData() does not call any observer methods if it is dispatched
449 // after the timeout.
450 RunDeferredCallback();
451 fetcher->set_weak_observer(nullptr);
452 }
453 }
454
455 TEST_P(AddToHomescreenDataFetcherTestCommon, InstallableManifest) {
456 // Test an installable manifest for a site that has a service worker.
457 content::Manifest manifest(BuildDefaultManifest());
458 SetManifest(manifest);
459
460 ObserverWaiter waiter;
461 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter));
462 RunFetcher(fetcher, waiter, kDefaultManifestShortName,
463 blink::kWebDisplayModeStandalone, check_webapk_compatibility());
464 EXPECT_TRUE(IsDeferredCallbackNull());
465
466 // There should always be a primary icon. The badge icon should only be
467 // present if we checked for WebAPK compatibility.
468 EXPECT_FALSE(fetcher->primary_icon().drawsNothing());
469 EXPECT_EQ(fetcher->shortcut_info().best_primary_icon_url,
470 GURL(kDefaultIconUrl));
326 EXPECT_EQ(check_webapk_compatibility(), 471 EXPECT_EQ(check_webapk_compatibility(),
327 waiter.determined_webapk_compatibility()); 472 !fetcher->badge_icon().drawsNothing());
328 EXPECT_FALSE(waiter.is_webapk_compatible()); 473 EXPECT_EQ(check_webapk_compatibility(),
329 EXPECT_TRUE(waiter.title_available()); 474 !fetcher->shortcut_info().best_badge_icon_url.is_empty());
330 EXPECT_TRUE(base::EqualsASCII(waiter.title(), kWebApplicationInfoTitle)); 475 fetcher->set_weak_observer(nullptr);
331 476 }
332 fetcher->set_weak_observer(nullptr); 477
333 } 478 TEST_P(AddToHomescreenDataFetcherTestCommon, BadgeIconRequest) {
334 479 // Check that the badge icon is requested only when AddToHomescreenDataFetcher
335 // Test that when the manifest provides Manifest::short_name but not 480 // checks for WebAPK compatibility.
336 // Manifest::name that Manifest::short_name is used as the name instead of 481 content::Manifest manifest(BuildDefaultManifest());
337 // WebApplicationInfo::title. 482
483 SetManifest(BuildDefaultManifest());
484 ObserverWaiter waiter;
pkotwicz 2017/06/30 23:54:52 The setup in this test seems identical to the setu
dominickn 2017/07/05 07:03:26 Done.
485 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter));
486 RunFetcher(fetcher, waiter, kDefaultManifestShortName,
487 blink::kWebDisplayModeStandalone, check_webapk_compatibility());
488 EXPECT_TRUE(IsDeferredCallbackNull());
489
490 EXPECT_FALSE(fetcher->primary_icon().drawsNothing());
491 EXPECT_EQ(fetcher->shortcut_info().best_primary_icon_url,
492 GURL(kDefaultIconUrl));
493 if (check_webapk_compatibility()) {
494 EXPECT_FALSE(fetcher->badge_icon().drawsNothing());
495 EXPECT_EQ(fetcher->shortcut_info().best_badge_icon_url,
496 GURL(kDefaultIconUrl));
497 }
498 fetcher->set_weak_observer(nullptr);
499 }
500
338 TEST_P(AddToHomescreenDataFetcherTestCommon, 501 TEST_P(AddToHomescreenDataFetcherTestCommon,
339 ManifestShortNameClobbersWebApplicationName) { 502 ManifestShortNameClobbersWebApplicationName) {
340 WebApplicationInfo web_application_info; 503 // Test that when the manifest provides Manifest::short_name but not
341 web_application_info.title = base::UTF8ToUTF16(kWebApplicationInfoTitle); 504 // Manifest::name that Manifest::short_name is used as the name.
pkotwicz 2017/06/30 23:54:52 Can we flip this test case around to have an empty
dominickn 2017/07/05 07:03:26 Done.
342 505 {
343 content::Manifest manifest(BuildDefaultManifest()); 506 // Check the case where we have no icons.
344 manifest.name = base::NullableString16(); 507 content::Manifest manifest = BuildDefaultManifest();
345 508 manifest.icons.clear();
346 RegisterServiceWorker(GURL(kDefaultStartUrl)); 509 manifest.name = base::NullableString16();
347 SetManifest(GURL(kDefaultManifestUrl), manifest); 510 SetManifest(manifest);
348 511
349 ObserverWaiter waiter; 512 ObserverWaiter waiter;
350 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter)); 513 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter));
351 fetcher->OnDidGetWebApplicationInfo(web_application_info); 514 RunFetcher(fetcher, waiter, kDefaultManifestShortName,
352 waiter.WaitForDataAvailable(); 515 blink::kWebDisplayModeStandalone, false);
353 516 EXPECT_TRUE(IsDeferredCallbackNull());
354 EXPECT_TRUE(base::EqualsASCII(waiter.title(), kDefaultManifestShortName)); 517
355 EXPECT_TRUE(base::EqualsASCII(fetcher->shortcut_info().name, 518 EXPECT_TRUE(fetcher->primary_icon().drawsNothing());
356 kDefaultManifestShortName)); 519 EXPECT_TRUE(fetcher->shortcut_info().best_primary_icon_url.is_empty());
357 520 EXPECT_TRUE(base::EqualsASCII(fetcher->shortcut_info().name,
358 fetcher->set_weak_observer(nullptr); 521 kDefaultManifestShortName));
359 } 522
360 523 fetcher->set_weak_observer(nullptr);
361 // Test that when the manifest does not provide either Manifest::short_name nor 524 }
362 // Manifest::name that: 525
363 // - The page is not WebAPK compatible. 526 {
364 // - WebApplicationInfo::title is used as the "name". 527 // Check a site with no service worker.
528 content::Manifest manifest(BuildDefaultManifest());
529 manifest.name = base::NullableString16();
530 SetManifest(manifest);
531 SetShouldInstallableTimeOut(true);
532 SetInstallable(false);
533
534 ObserverWaiter waiter;
535 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter));
536 RunFetcher(fetcher, waiter, kDefaultManifestShortName,
537 blink::kWebDisplayModeStandalone, false);
538
539 EXPECT_FALSE(fetcher->primary_icon().drawsNothing());
540 EXPECT_EQ(fetcher->shortcut_info().best_primary_icon_url,
541 GURL(kDefaultIconUrl));
542 EXPECT_TRUE(base::EqualsASCII(fetcher->shortcut_info().name,
543 kDefaultManifestShortName));
544
545 if (check_webapk_compatibility()) {
546 // GetData() should have timed out waiting for a service worker to be
547 // registered. Test that the GetData() call does not call any observer
548 // methods a second time.
549 RunDeferredCallback();
550 }
551
552 EXPECT_TRUE(IsDeferredCallbackNull());
553 fetcher->set_weak_observer(nullptr);
554 }
555
556 {
557 // Check a site with a service worker, but the service worker check times
558 // out because its too slow. The deferred callback will have
559 // NO_ERROR_DETECTED instead of NOT_OFFLINE_CAPABLE.
560 SetShouldInstallableTimeOut(true);
561 SetInstallable(true);
562
563 ObserverWaiter waiter;
564 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter));
565 RunFetcher(fetcher, waiter, kDefaultManifestShortName,
566 blink::kWebDisplayModeStandalone, false);
567
568 EXPECT_FALSE(fetcher->primary_icon().drawsNothing());
569 EXPECT_EQ(fetcher->shortcut_info().best_primary_icon_url,
570 GURL(kDefaultIconUrl));
571 EXPECT_TRUE(base::EqualsASCII(fetcher->shortcut_info().name,
572 kDefaultManifestShortName));
573
574 if (check_webapk_compatibility()) {
575 // Test that the GetData() call does not call any observer methods a
576 // second time.
577 RunDeferredCallback();
578 }
579
580 EXPECT_TRUE(IsDeferredCallbackNull());
581 fetcher->set_weak_observer(nullptr);
582 }
583
584 {
585 // Check a site with a service worker.
586 SetShouldInstallableTimeOut(false);
587 SetInstallable(true);
588 ObserverWaiter waiter;
589 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter));
590 RunFetcher(fetcher, waiter, kDefaultManifestShortName,
591 blink::kWebDisplayModeStandalone, check_webapk_compatibility());
592 EXPECT_TRUE(IsDeferredCallbackNull());
593
594 EXPECT_FALSE(fetcher->primary_icon().drawsNothing());
595 EXPECT_EQ(fetcher->shortcut_info().best_primary_icon_url,
596 GURL(kDefaultIconUrl));
597 EXPECT_TRUE(base::EqualsASCII(fetcher->shortcut_info().name,
598 kDefaultManifestShortName));
599
600 fetcher->set_weak_observer(nullptr);
601 }
602 }
603
365 TEST_P(AddToHomescreenDataFetcherTestCommon, ManifestNoNameNoShortName) { 604 TEST_P(AddToHomescreenDataFetcherTestCommon, ManifestNoNameNoShortName) {
366 WebApplicationInfo web_application_info; 605 // Test that when the manifest does not provide either Manifest::short_name
367 web_application_info.title = base::UTF8ToUTF16(kWebApplicationInfoTitle); 606 // nor Manifest::name that:
368 607 // - The page is not WebAPK compatible.
608 // - WebApplicationInfo::title is used as the "name".
609 // - We still use the icons from the manifest.
369 content::Manifest manifest(BuildDefaultManifest()); 610 content::Manifest manifest(BuildDefaultManifest());
370 manifest.name = base::NullableString16(); 611 manifest.name = base::NullableString16();
371 manifest.short_name = base::NullableString16(); 612 manifest.short_name = base::NullableString16();
372 613
373 RegisterServiceWorker(GURL(kDefaultStartUrl)); 614 // Check the case where we don't time out waiting for the service worker.
374 SetManifest(GURL(kDefaultManifestUrl), manifest); 615 SetManifest(manifest);
375 616 SetShouldInstallableTimeOut(false);
376 ObserverWaiter waiter; 617 ObserverWaiter waiter;
377 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter)); 618 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter));
378 fetcher->OnDidGetWebApplicationInfo(web_application_info); 619 RunFetcher(fetcher, waiter, kWebApplicationInfoTitle,
379 waiter.WaitForDataAvailable(); 620 blink::kWebDisplayModeStandalone, false);
380 621 EXPECT_TRUE(IsDeferredCallbackNull());
381 EXPECT_EQ(check_webapk_compatibility(), 622
382 waiter.determined_webapk_compatibility());
383 EXPECT_FALSE(waiter.is_webapk_compatible());
384 EXPECT_TRUE(base::EqualsASCII(waiter.title(), kWebApplicationInfoTitle));
385 EXPECT_TRUE(base::EqualsASCII(fetcher->shortcut_info().name, 623 EXPECT_TRUE(base::EqualsASCII(fetcher->shortcut_info().name,
386 kWebApplicationInfoTitle)); 624 kWebApplicationInfoTitle));
387 625 EXPECT_TRUE(base::EqualsASCII(fetcher->shortcut_info().short_name,
388 fetcher->set_weak_observer(nullptr); 626 kWebApplicationInfoTitle));
389 } 627 EXPECT_FALSE(fetcher->primary_icon().drawsNothing());
390 628 EXPECT_EQ(fetcher->shortcut_info().best_primary_icon_url,
391 // Checks that the AddToHomescreenDataFetcher::Observer callbacks are called 629 GURL(kDefaultIconUrl));
392 // when the manifest fetch times out. 630
393 TEST_P(AddToHomescreenDataFetcherTestCommon, ManifestFetchTimesOut) { 631 fetcher->set_weak_observer(nullptr);
394 WebApplicationInfo web_application_info; 632 }
395 web_application_info.title = base::UTF8ToUTF16(kWebApplicationInfoTitle);
396
397 RegisterServiceWorker(GURL(kDefaultStartUrl));
398 SetManifest(GURL(kDefaultManifestUrl), BuildDefaultManifest());
399 SetShouldManifestTimeOut(true);
400 SetShouldImageTimeOut(false);
401
402 ObserverWaiter waiter;
403 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter));
404 fetcher->OnDidGetWebApplicationInfo(web_application_info);
405 waiter.WaitForDataAvailable();
406
407 EXPECT_EQ(check_webapk_compatibility(),
408 waiter.determined_webapk_compatibility());
409 EXPECT_FALSE(waiter.is_webapk_compatible());
410 EXPECT_TRUE(base::EqualsASCII(waiter.title(), kWebApplicationInfoTitle));
411 EXPECT_TRUE(waiter.title_available());
412
413 fetcher->set_weak_observer(nullptr);
414 }
415
416 // Checks that the AddToHomescreenDataFetcher::Observer callbacks are called
417 // when the image fetch times out.
418 TEST_P(AddToHomescreenDataFetcherTestCommon, ImageFetchTimesOut) {
419 WebApplicationInfo web_application_info;
420 web_application_info.title = base::UTF8ToUTF16(kWebApplicationInfoTitle);
421
422 RegisterServiceWorker(GURL(kDefaultStartUrl));
423 SetManifest(GURL(kDefaultManifestUrl), BuildDefaultManifest());
424 SetShouldManifestTimeOut(false);
425 SetShouldImageTimeOut(true);
426
427 ObserverWaiter waiter;
428 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter));
429 fetcher->OnDidGetWebApplicationInfo(web_application_info);
430 waiter.WaitForDataAvailable();
431
432 EXPECT_EQ(check_webapk_compatibility(),
433 waiter.determined_webapk_compatibility());
434 EXPECT_FALSE(waiter.is_webapk_compatible());
435 EXPECT_TRUE(waiter.title_available());
436 EXPECT_TRUE(base::EqualsASCII(waiter.title(), kWebApplicationInfoTitle));
437
438 fetcher->set_weak_observer(nullptr);
439 }
440
441 // Checks that the AddToHomescreenDataFetcher::Observer callbacks are called
442 // when the service worker check times out.
443 TEST_P(AddToHomescreenDataFetcherTestCommon, ServiceWorkerCheckTimesOut) {
444 WebApplicationInfo web_application_info;
445 web_application_info.title = base::UTF8ToUTF16(kWebApplicationInfoTitle);
446
447 // Not registering a service worker means we'll wait and time out for the
448 // worker.
449 SetManifest(GURL(kDefaultManifestUrl), BuildDefaultManifest());
450 SetShouldManifestTimeOut(false);
451 SetShouldImageTimeOut(false);
452
453 ObserverWaiter waiter;
454 scoped_refptr<AddToHomescreenDataFetcher> fetcher(BuildFetcher(&waiter));
455 fetcher->OnDidGetWebApplicationInfo(web_application_info);
456 waiter.WaitForDataAvailable();
457
458 EXPECT_EQ(check_webapk_compatibility(),
459 waiter.determined_webapk_compatibility());
460 EXPECT_FALSE(waiter.is_webapk_compatible());
461 EXPECT_TRUE(waiter.title_available());
462 EXPECT_TRUE(base::EqualsASCII(waiter.title(), kDefaultManifestShortName));
463 EXPECT_TRUE(base::EqualsASCII(fetcher->shortcut_info().user_title,
464 kDefaultManifestShortName));
465
466 fetcher->set_weak_observer(nullptr);
467 }
468 633
469 INSTANTIATE_TEST_CASE_P(CheckWebApkCompatibility, 634 INSTANTIATE_TEST_CASE_P(CheckWebApkCompatibility,
470 AddToHomescreenDataFetcherTestCommon, 635 AddToHomescreenDataFetcherTestCommon,
471 ::testing::Values(false, true)); 636 ::testing::Values(false, true));
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/installable/installable_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698