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

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

Issue 2741283002: Idea for AddToHomescreenDataFetcher tests
Patch Set: Created 3 years, 9 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 | « chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h ('k') | chrome/test/BUILD.gn » ('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 9
10 #include "base/bind.h"
10 #include "base/callback_forward.h" 11 #include "base/callback_forward.h"
11 #include "base/files/file_path.h" 12 #include "base/files/file_path.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/message_loop/message_loop.h"
15 #include "base/run_loop.h" 16 #include "base/run_loop.h"
16 #include "base/strings/nullable_string16.h" 17 #include "base/strings/nullable_string16.h"
17 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
18 #include "base/strings/utf_string_conversions.h" 19 #include "base/strings/utf_string_conversions.h"
20 #include "base/test/test_mock_time_task_runner.h"
19 #include "base/time/time.h" 21 #include "base/time/time.h"
22 #include "chrome/browser/favicon/favicon_service_factory.h"
23 #include "chrome/browser/installable/installable_manager.h"
20 #include "chrome/common/web_application_info.h" 24 #include "chrome/common/web_application_info.h"
21 #include "chrome/test/base/chrome_render_view_host_test_harness.h" 25 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
22 #include "chrome/test/base/testing_profile.h" 26 #include "chrome/test/base/testing_profile.h"
27 #include "components/favicon/core/favicon_service.h"
28 #include "components/favicon/core/test/mock_favicon_service.h"
23 #include "content/browser/service_worker/embedded_worker_test_helper.h" 29 #include "content/browser/service_worker/embedded_worker_test_helper.h"
24 #include "content/browser/service_worker/service_worker_context_core.h" 30 #include "content/browser/service_worker/service_worker_context_core.h"
25 #include "content/common/service_worker/service_worker_status_code.h" 31 #include "content/common/service_worker/service_worker_status_code.h"
26 #include "content/public/browser/browser_thread.h" 32 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/site_instance.h" 33 #include "content/public/browser/site_instance.h"
28 #include "content/public/browser/web_contents.h" 34 #include "content/public/browser/web_contents.h"
29 #include "content/public/common/manifest.h" 35 #include "content/public/common/manifest.h"
30 #include "content/test/test_web_contents.h" 36 #include "content/test/test_web_contents.h"
31 #include "net/http/http_status_code.h" 37 #include "net/http/http_status_code.h"
38 #include "testing/gmock/include/gmock/gmock.h"
39 #include "third_party/skia/include/core/SkBitmap.h"
32 #include "third_party/WebKit/public/platform/WebDisplayMode.h" 40 #include "third_party/WebKit/public/platform/WebDisplayMode.h"
33 #include "ui/gfx/image/image_unittest_util.h" 41 #include "ui/gfx/image/image_unittest_util.h"
34 #include "url/gurl.h" 42 #include "url/gurl.h"
35 43
36 // TODO(zpeng): Effectively test scenarios where both timeout callback and 44 // TODO(zpeng): Effectively test scenarios where both timeout callback and
37 // success callback are invoked. See crbug.com/697228. 45 // success callback are invoked. See crbug.com/697228.
38 46
39 namespace { 47 namespace {
40 48
41 const char* kDefaultManifestUrl = "https://www.example.com/manifest.json";
42 const char* kDefaultManifestName = "Default Name"; 49 const char* kDefaultManifestName = "Default Name";
43 const char* kDefaultManifestShortName = "Default Short Name"; 50 const char* kDefaultManifestShortName = "Default Short Name";
44 const char* kDefaultStartUrl = "https://www.example.com/index.html";
45 const blink::WebDisplayMode kDefaultManifestDisplayMode = 51 const blink::WebDisplayMode kDefaultManifestDisplayMode =
46 blink::WebDisplayModeStandalone; 52 blink::WebDisplayModeStandalone;
53 const GURL kDefaultManifestUrl("https://www.example.com/manifest.json");
54 const GURL kDefaultStartUrl("https://www.example.com/index.html");
55 const GURL kDefaultPrimaryIconUrl("https://www.example.com/icon.png");
56 const GURL kEmptyUrl;
47 57
48 // WebContents subclass which mocks out image and manifest fetching. 58
49 class MockWebContents : public content::TestWebContents { 59 class TestInstallableManager : public InstallableManager {
50 public: 60 public:
51 explicit MockWebContents(content::BrowserContext* browser_context) 61 TestInstallableManager() : InstallableManager(nullptr) {}
52 : content::TestWebContents(browser_context) {} 62 ~TestInstallableManager() override {}
53 63
54 ~MockWebContents() override { 64 static void CreateForWebContents(content::WebContents* web_contents) {
65 if (!FromWebContents(web_contents))
66 web_contents->SetUserData(UserDataKey(), new TestInstallableManager());
55 } 67 }
56 68
57 // Sets the manifest to be returned by GetManifest(). 69 void GetData(const InstallableParams& params,
58 // |fetch_delay_ms| is the time in milliseconds that the simulated fetch of 70 const InstallableCallback& callback) override {
59 // the web manifest should take. 71 callback_ = callback;
60 void SetManifest(const GURL& manifest_url,
61 const content::Manifest& manifest,
62 int fetch_delay_ms) {
63 manifest_url_ = manifest_url;
64 manifest_ = manifest;
65 manifest_fetch_delay_ms_ = fetch_delay_ms;
66 } 72 }
67 73
68 int DownloadImage(const GURL& url, 74 InstallableCallback callback_;
69 bool is_favicon,
70 uint32_t max_bitmap_size,
71 bool bypass_cache,
72 const ImageDownloadCallback& callback) override {
73 const int kIconSizePx = 144;
74 SkBitmap icon = gfx::test::CreateBitmap(kIconSizePx, kIconSizePx);
75 std::vector<SkBitmap> icons(1u, icon);
76 std::vector<gfx::Size> pixel_sizes(1u, gfx::Size(kIconSizePx, kIconSizePx));
77 content::BrowserThread::PostTask(
78 content::BrowserThread::UI,
79 FROM_HERE,
80 base::Bind(callback, 0, net::HTTP_OK, url, icons, pixel_sizes));
81 return 0;
82 }
83 75
84 void GetManifest(const GetManifestCallback& callback) override { 76 private:
85 content::BrowserThread::PostDelayedTask( 77 DISALLOW_COPY_AND_ASSIGN(TestInstallableManager);
86 content::BrowserThread::UI, FROM_HERE, 78 };
87 base::Bind(callback, manifest_url_, manifest_), 79
88 base::TimeDelta::FromMilliseconds(manifest_fetch_delay_ms_)); 80 // Builds non-null base::NullableString16 from a UTF8 string.
81 base::NullableString16 NullableStringFromUTF8(const std::string& value) {
82 return base::NullableString16(base::UTF8ToUTF16(value), false);
83 }
84
85 class InstallableDataBuilder {
86 public:
87 InstallableDataBuilder() {}
88
89 InstallableData Build() {
90 primary_icon_ = gfx::test::CreateBitmap(144, 144);
91 manifest_.name = NullableStringFromUTF8(kDefaultManifestName);
92 manifest_.short_name = NullableStringFromUTF8(kDefaultManifestShortName);
93 manifest_.start_url = GURL(kDefaultStartUrl);
94 manifest_.display = kDefaultManifestDisplayMode;
95
96 return {NO_ERROR_DETECTED, kDefaultManifestUrl,
97 manifest_, kDefaultPrimaryIconUrl,
98 &primary_icon_, kEmptyUrl,
99 nullptr, true};
89 } 100 }
90 101
91 private: 102 private:
92 GURL manifest_url_;
93 content::Manifest manifest_; 103 content::Manifest manifest_;
94 int manifest_fetch_delay_ms_; 104 SkBitmap primary_icon_;
95 105
96 DISALLOW_COPY_AND_ASSIGN(MockWebContents); 106 DISALLOW_COPY_AND_ASSIGN(InstallableDataBuilder);
97 }; 107 };
98 108
99 // Tracks which of the AddToHomescreenDataFetcher::Observer callbacks have been 109 // Tracks which of the AddToHomescreenDataFetcher::Observer callbacks have been
100 // called. 110 // called.
101 class ObserverWaiter : public AddToHomescreenDataFetcher::Observer { 111 class TestObserver : public AddToHomescreenDataFetcher::Observer {
102 public: 112 public:
103 ObserverWaiter() 113 TestObserver()
104 : is_webapk_compatible_(false), 114 : is_webapk_compatible_(false),
105 determined_webapk_compatibility_(false), 115 determined_webapk_compatibility_(false),
106 title_available_(false), 116 title_available_(false),
107 data_available_(false) {} 117 data_available_(false) {}
108 ~ObserverWaiter() override {} 118 ~TestObserver() override {}
109
110 // Waits till the OnDataAvailable() callback is called.
111 void WaitForDataAvailable() {
112 if (data_available_)
113 return;
114
115 base::RunLoop run_loop;
116 quit_closure_ = run_loop.QuitClosure();
117 run_loop.Run();
118 }
119 119
120 void OnDidDetermineWebApkCompatibility(bool is_webapk_compatible) override { 120 void OnDidDetermineWebApkCompatibility(bool is_webapk_compatible) override {
121 determined_webapk_compatibility_ = true; 121 determined_webapk_compatibility_ = true;
122 is_webapk_compatible_ = is_webapk_compatible; 122 is_webapk_compatible_ = is_webapk_compatible;
123 } 123 }
124 124
125 void OnUserTitleAvailable(const base::string16& title) override { 125 void OnUserTitleAvailable(const base::string16& title) override {
126 title_available_ = true; 126 title_available_ = true;
127 } 127 }
128 128
129 SkBitmap FinalizeLauncherIconInBackground(const SkBitmap& icon, 129 SkBitmap FinalizeLauncherIconInBackground(const SkBitmap& icon,
130 const GURL& url, 130 const GURL& url,
131 bool* is_generated) override { 131 bool* is_generated) override {
132 *is_generated = false; 132 *is_generated = false;
133 return icon; 133 return icon;
134 } 134 }
135 135
136 void OnDataAvailable(const ShortcutInfo& info, 136 void OnDataAvailable(const ShortcutInfo& info,
137 const SkBitmap& primary_icon, 137 const SkBitmap& primary_icon,
138 const SkBitmap& badge_icon) override { 138 const SkBitmap& badge_icon) override {
139 data_available_ = true; 139 data_available_ = true;
140 if (!quit_closure_.is_null())
141 quit_closure_.Run();
142 } 140 }
143 141
144 bool is_webapk_compatible() const { return is_webapk_compatible_; } 142 bool is_webapk_compatible() const { return is_webapk_compatible_; }
145 bool determined_webapk_compatibility() const { 143 bool determined_webapk_compatibility() const {
146 return determined_webapk_compatibility_; 144 return determined_webapk_compatibility_;
147 } 145 }
148 bool title_available() const { return title_available_; } 146 bool title_available() const { return title_available_; }
147 bool data_available() const { return data_available_; }
149 148
150 private: 149 private:
151 bool is_webapk_compatible_; 150 bool is_webapk_compatible_;
152 bool determined_webapk_compatibility_; 151 bool determined_webapk_compatibility_;
153 bool title_available_; 152 bool title_available_;
154 bool data_available_; 153 bool data_available_;
155 base::Closure quit_closure_;
156 154
157 DISALLOW_COPY_AND_ASSIGN(ObserverWaiter); 155 DISALLOW_COPY_AND_ASSIGN(TestObserver);
158 }; 156 };
159 157
160 // Builds non-null base::NullableString16 from a UTF8 string. 158 std::unique_ptr<KeyedService> BuildMockFaviconService(
161 base::NullableString16 NullableStringFromUTF8(const std::string& value) { 159 content::BrowserContext* context) {
162 return base::NullableString16(base::UTF8ToUTF16(value), false); 160 return std::unique_ptr<KeyedService>(
163 } 161 new testing::NiceMock<favicon::MockFaviconService>);
164
165 // Builds WebAPK compatible content::Manifest.
166 content::Manifest BuildDefaultManifest() {
167 content::Manifest manifest;
168 manifest.name = NullableStringFromUTF8(kDefaultManifestName);
169 manifest.short_name = NullableStringFromUTF8(kDefaultManifestShortName);
170 manifest.start_url = GURL(kDefaultStartUrl);
171 manifest.display = kDefaultManifestDisplayMode;
172 return manifest;
173 } 162 }
174 163
175 } // anonymous namespace 164 } // anonymous namespace
176 165
177 // Tests AddToHomescreenDataFetcher. These tests should be browser tests but 166 // Tests AddToHomescreenDataFetcher. These tests should be browser tests but
178 // Android does not support browser tests yet (crbug.com/611756). 167 // Android does not support browser tests yet (crbug.com/611756).
179 class AddToHomescreenDataFetcherTest : public ChromeRenderViewHostTestHarness { 168 class AddToHomescreenDataFetcherTest : public ChromeRenderViewHostTestHarness {
180 public: 169 public:
181 AddToHomescreenDataFetcherTest() {} 170 AddToHomescreenDataFetcherTest()
171 : timer_task_runner_(new base::TestMockTimeTaskRunner) {}
182 ~AddToHomescreenDataFetcherTest() override {} 172 ~AddToHomescreenDataFetcherTest() override {}
183 173
184 void SetUp() override { 174 void SetUp() override {
185 ChromeRenderViewHostTestHarness::SetUp(); 175 ChromeRenderViewHostTestHarness::SetUp();
186 176
187 ASSERT_TRUE(profile()->CreateHistoryService(false, true)); 177 // Make InstallableManager::GetForWebContents() return a
188 profile()->CreateFaviconService(); 178 // TestInstallableManager.
179 TestInstallableManager::CreateForWebContents(web_contents());
189 180
190 embedded_worker_test_helper_.reset( 181 FaviconServiceFactory::GetInstance()->SetTestingFactory(
191 new content::EmbeddedWorkerTestHelper(base::FilePath())); 182 browser_context(), &BuildMockFaviconService);
192
193 scoped_refptr<content::SiteInstance> site_instance =
194 content::SiteInstance::Create(browser_context());
195 site_instance->GetProcess()->Init();
196 MockWebContents* mock_web_contents = new MockWebContents(browser_context());
197 mock_web_contents->Init(content::WebContents::CreateParams(
198 browser_context(), std::move(site_instance)));
199 SetContents(mock_web_contents);
200 } 183 }
201 184
202 void TearDown() override { 185 TestInstallableManager* test_installable_manager() {
203 embedded_worker_test_helper_.reset(); 186 return static_cast<TestInstallableManager*>(
204 ChromeRenderViewHostTestHarness::TearDown(); 187 InstallableManager::FromWebContents(web_contents()));
205 } 188 }
206 189
207 scoped_refptr<AddToHomescreenDataFetcher> BuildFetcher( 190 scoped_refptr<AddToHomescreenDataFetcher> BuildFetcher(
208 bool check_webapk_compatible, 191 bool check_webapk_compatible,
209 AddToHomescreenDataFetcher::Observer* observer) { 192 AddToHomescreenDataFetcher::Observer* observer) {
210 return new AddToHomescreenDataFetcher(web_contents(), 1, 1, 1, 1, 1, 193 scoped_refptr<AddToHomescreenDataFetcher> fetcher(
211 check_webapk_compatible, observer); 194 new AddToHomescreenDataFetcher(web_contents(), 1, 1, 1, 1, 1,
195 check_webapk_compatible, observer));
196 fetcher->data_timeout_timer_.SetTaskRunner(timer_task_runner_);
197 return fetcher;
212 } 198 }
213 199
214 // Set the manifest to be returned as a result of WebContents::GetManifest(). 200 scoped_refptr<base::TestMockTimeTaskRunner> timer_task_runner_;
215 void SetManifest(const GURL& manifest_url,
216 const content::Manifest& manifest,
217 int fetch_delay_ms) {
218 MockWebContents* mock_web_contents =
219 static_cast<MockWebContents*>(web_contents());
220 mock_web_contents->SetManifest(manifest_url, manifest, fetch_delay_ms);
221 }
222
223 // Registers service worker at |url|. Blocks till the service worker is
224 // registered.
225 void RegisterServiceWorker(const GURL& url) {
226 base::RunLoop run_loop;
227 embedded_worker_test_helper_->context()->RegisterServiceWorker(
228 url, GURL(url.spec() + "/service_worker.js"), nullptr,
229 base::Bind(&AddToHomescreenDataFetcherTest::OnServiceWorkerRegistered,
230 base::Unretained(this), run_loop.QuitClosure()));
231 }
232 201
233 private: 202 private:
234 // Callback for RegisterServiceWorker() for when service worker registration
235 // has completed.
236 void OnServiceWorkerRegistered(const base::Closure& callback,
237 content::ServiceWorkerStatusCode status,
238 const std::string& status_message,
239 int64_t registration_id) {
240 ASSERT_EQ(content::SERVICE_WORKER_OK, status)
241 << content::ServiceWorkerStatusToString(status);
242 callback.Run();
243 }
244
245 std::unique_ptr<content::EmbeddedWorkerTestHelper>
246 embedded_worker_test_helper_;
247
248 DISALLOW_COPY_AND_ASSIGN(AddToHomescreenDataFetcherTest); 203 DISALLOW_COPY_AND_ASSIGN(AddToHomescreenDataFetcherTest);
249 }; 204 };
250 205
251 // Checks that AddToHomescreenDataFetcher::Observer::OnUserTitleAvailable() is 206 TEST_F(AddToHomescreenDataFetcherTest, ManifestFetchTimesOut) {
252 // called when the web manifest fetch times out. The add-to-homescreen dialog 207 TestObserver observer;
253 // makes the dialog's text field editable once OnUserTitleAvailable() is called. 208 scoped_refptr<AddToHomescreenDataFetcher> fetcher(
254 TEST_F(AddToHomescreenDataFetcherTest, 209 BuildFetcher(false, &observer));
255 DISABLED_ManifestFetchTimesOutNoServiceWorker) { 210 fetcher->OnDidGetWebApplicationInfo(WebApplicationInfo());
256 SetManifest(GURL(kDefaultManifestUrl), BuildDefaultManifest(), 10000); 211 ASSERT_FALSE(test_installable_manager()->callback_.is_null());
212 ASSERT_TRUE(timer_task_runner_->HasPendingTask());
213 timer_task_runner_->FastForwardUntilNoTasksRemain();
214 content::BrowserThread::GetBlockingPool()->FlushForTesting();
257 215
258 ObserverWaiter waiter; 216 // Eventually manifest fetch finishes.
259 scoped_refptr<AddToHomescreenDataFetcher> fetcher( 217 InstallableDataBuilder builder;
260 BuildFetcher(false, &waiter)); 218 test_installable_manager()->callback_.Run(builder.Build());
261 fetcher->OnDidGetWebApplicationInfo(WebApplicationInfo());
262 waiter.WaitForDataAvailable();
263 219
264 EXPECT_FALSE(waiter.determined_webapk_compatibility()); 220 EXPECT_FALSE(observer.determined_webapk_compatibility());
265 EXPECT_TRUE(waiter.title_available()); 221 EXPECT_TRUE(observer.title_available());
222 EXPECT_TRUE(observer.data_available());
266 223
267 fetcher->set_weak_observer(nullptr); 224 fetcher->set_weak_observer(nullptr);
268 } 225 }
269 226
227 /*
270 // Class for tests which should be run with AddToHomescreenDataFetcher built 228 // Class for tests which should be run with AddToHomescreenDataFetcher built
271 // with both true and false values of |check_webapk_compatible|. 229 // with both true and false values of |check_webapk_compatible|.
272 class AddToHomescreenDataFetcherTestCommon 230 class AddToHomescreenDataFetcherTestCommon
273 : public AddToHomescreenDataFetcherTest, 231 : public AddToHomescreenDataFetcherTest,
274 public testing::WithParamInterface<bool> { 232 public testing::WithParamInterface<bool> {
275 public: 233 public:
276 AddToHomescreenDataFetcherTestCommon() {} 234 AddToHomescreenDataFetcherTestCommon() {}
277 ~AddToHomescreenDataFetcherTestCommon() override {} 235 ~AddToHomescreenDataFetcherTestCommon() override {}
278 236
279 scoped_refptr<AddToHomescreenDataFetcher> BuildFetcher( 237 scoped_refptr<AddToHomescreenDataFetcher> BuildFetcher(
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 } 320 }
363 // This callback enables the text field in the add-to-homescreen dialog. 321 // This callback enables the text field in the add-to-homescreen dialog.
364 EXPECT_TRUE(waiter.title_available()); 322 EXPECT_TRUE(waiter.title_available());
365 323
366 fetcher->set_weak_observer(nullptr); 324 fetcher->set_weak_observer(nullptr);
367 } 325 }
368 326
369 INSTANTIATE_TEST_CASE_P(CheckWebApkCompatibility, 327 INSTANTIATE_TEST_CASE_P(CheckWebApkCompatibility,
370 AddToHomescreenDataFetcherTestCommon, 328 AddToHomescreenDataFetcherTestCommon,
371 ::testing::Values(false, true)); 329 ::testing::Values(false, true));
330 */
OLDNEW
« no previous file with comments | « chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h ('k') | chrome/test/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698