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

Side by Side Diff: chrome/browser/android/offline_pages/offline_page_tab_helper_unittest.cc

Issue 2284933002: Remove OfflineURL from offline page (Closed)
Patch Set: Add comment per feedback Created 4 years, 2 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/android/offline_pages/offline_page_tab_helper.h"
6
7 #include <memory>
8
9 #include "base/bind.h"
10 #include "base/feature_list.h"
11 #include "base/files/file_path.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/metrics/field_trial.h"
15 #include "base/run_loop.h"
16 #include "base/strings/string16.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/test/histogram_tester.h"
20 #include "base/test/simple_test_clock.h"
21 #include "base/time/time.h"
22 #include "chrome/browser/android/offline_pages/offline_page_model_factory.h"
23 #include "chrome/browser/android/offline_pages/offline_page_utils.h"
24 #include "chrome/browser/android/offline_pages/test_offline_page_model_builder.h "
25 #include "chrome/browser/net/nqe/ui_network_quality_estimator_service.h"
26 #include "chrome/browser/net/nqe/ui_network_quality_estimator_service_factory.h"
27 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
28 #include "chrome/test/base/testing_profile.h"
29 #include "components/offline_pages/client_namespace_constants.h"
30 #include "components/offline_pages/offline_page_feature.h"
31 #include "components/offline_pages/offline_page_item.h"
32 #include "components/offline_pages/offline_page_model.h"
33 #include "components/offline_pages/offline_page_test_archiver.h"
34 #include "components/offline_pages/offline_page_types.h"
35 #include "components/previews/core/previews_experiments.h"
36 #include "content/public/browser/navigation_entry.h"
37 #include "content/public/browser/web_contents.h"
38 #include "net/base/net_errors.h"
39 #include "net/base/network_change_notifier.h"
40 #include "net/nqe/network_quality_estimator.h"
41 #include "testing/gtest/include/gtest/gtest.h"
42
43 namespace offline_pages {
44
45 namespace {
46
47 const GURL kTestPageUrl("http://test.org/page1");
48 const ClientId kTestClientId = ClientId(kBookmarkNamespace, "1234");
49 const int64_t kTestFileSize = 876543LL;
50 const base::string16 kTestTitle = base::UTF8ToUTF16("a title");
51 const char kRedirectResultHistogram[] = "OfflinePages.RedirectResult";
52 const int kTabId = 42;
53
54 class TestNetworkChangeNotifier : public net::NetworkChangeNotifier {
55 public:
56 TestNetworkChangeNotifier() : online_(true) {}
57
58 net::NetworkChangeNotifier::ConnectionType GetCurrentConnectionType()
59 const override {
60 return online_ ? net::NetworkChangeNotifier::CONNECTION_UNKNOWN
61 : net::NetworkChangeNotifier::CONNECTION_NONE;
62 }
63
64 void set_online(bool online) { online_ = online; }
65
66 private:
67 bool online_;
68
69 DISALLOW_COPY_AND_ASSIGN(TestNetworkChangeNotifier);
70 };
71
72 class TestDelegate : public OfflinePageTabHelper::Delegate {
73 public:
74 TestDelegate(bool has_tab_android,
75 int tab_id,
76 base::SimpleTestClock* clock)
77 : clock_(clock), has_tab_android_(has_tab_android), tab_id_(tab_id) {}
78 ~TestDelegate() override {}
79
80 // offline_pages::OfflinePageTabHelper::Delegate implementation:
81 bool GetTabId(content::WebContents* web_contents,
82 int* tab_id) const override {
83 if (has_tab_android_)
84 *tab_id = tab_id_;
85 return has_tab_android_;
86 }
87
88 base::Time Now() const override { return clock_->Now(); }
89
90 private:
91 base::SimpleTestClock* clock_;
92 bool has_tab_android_;
93 int tab_id_;
94 };
95
96 } // namespace
97
98 class OfflinePageTabHelperTest :
99 public ChromeRenderViewHostTestHarness,
100 public OfflinePageTestArchiver::Observer,
101 public base::SupportsWeakPtr<OfflinePageTabHelperTest> {
102 public:
103 OfflinePageTabHelperTest()
104 : network_change_notifier_(new TestNetworkChangeNotifier()),
105 clock_(new base::SimpleTestClock) {}
106 ~OfflinePageTabHelperTest() override {}
107
108 void SetUp() override;
109 void TearDown() override;
110
111 void RunUntilIdle();
112 void SimulateHasNetworkConnectivity(bool has_connectivity);
113 void StartLoad(const GURL& url);
114 void FailLoad(const GURL& url);
115 std::unique_ptr<OfflinePageTestArchiver> BuildArchiver(
116 const GURL& url,
117 const base::FilePath& file_name);
118 void OnSavePageDone(SavePageResult result, int64_t offline_id);
119
120 OfflinePageTabHelper* offline_page_tab_helper() const {
121 return offline_page_tab_helper_;
122 }
123
124 const GURL& online_url() const { return offline_page_item_->url; }
125 GURL offline_url() const { return offline_page_item_->GetOfflineURL(); }
126 int64_t offline_id() const { return offline_page_item_->offline_id; }
127
128 const base::HistogramTester& histograms() const { return histogram_tester_; }
129
130 base::SimpleTestClock* clock() { return clock_.get(); }
131
132 private:
133 // OfflinePageTestArchiver::Observer implementation:
134 void SetLastPathCreatedByArchiver(const base::FilePath& file_path) override;
135
136 void OnGetPageByOfflineIdDone(const OfflinePageItem* result);
137
138 std::unique_ptr<TestNetworkChangeNotifier> network_change_notifier_;
139 OfflinePageTabHelper* offline_page_tab_helper_; // Not owned.
140
141 std::unique_ptr<OfflinePageItem> offline_page_item_;
142
143 base::HistogramTester histogram_tester_;
144
145 std::unique_ptr<base::SimpleTestClock> clock_;
146
147 DISALLOW_COPY_AND_ASSIGN(OfflinePageTabHelperTest);
148 };
149
150 void OfflinePageTabHelperTest::SetUp() {
151 // Enables offline pages feature.
152 // TODO(jianli): Remove this once the feature is completely enabled.
153 base::FeatureList::ClearInstanceForTesting();
154 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
155 feature_list->InitializeFromCommandLine(
156 offline_pages::kOfflineBookmarksFeature.name, "");
157 base::FeatureList::SetInstance(std::move(feature_list));
158
159 // Creates a test web contents.
160 content::RenderViewHostTestHarness::SetUp();
161 OfflinePageTabHelper::CreateForWebContents(web_contents());
162 offline_page_tab_helper_ =
163 OfflinePageTabHelper::FromWebContents(web_contents());
164 offline_page_tab_helper_->SetDelegateForTesting(
165 base::MakeUnique<TestDelegate>(true, kTabId, clock_.get()));
166
167 // Sets up the factory for testing.
168 OfflinePageModelFactory::GetInstance()->SetTestingFactoryAndUse(
169 browser_context(), BuildTestOfflinePageModel);
170 RunUntilIdle();
171
172 // Saves an offline page.
173 OfflinePageModel* model =
174 OfflinePageModelFactory::GetForBrowserContext(browser_context());
175 std::unique_ptr<OfflinePageTestArchiver> archiver(BuildArchiver(
176 kTestPageUrl, base::FilePath(FILE_PATH_LITERAL("page1.mhtml"))));
177 model->SavePage(
178 kTestPageUrl, kTestClientId, 0l, std::move(archiver),
179 base::Bind(&OfflinePageTabHelperTest::OnSavePageDone, AsWeakPtr()));
180 RunUntilIdle();
181 }
182
183 void OfflinePageTabHelperTest::TearDown() {
184 content::RenderViewHostTestHarness::TearDown();
185 }
186
187 void OfflinePageTabHelperTest::RunUntilIdle() {
188 base::RunLoop().RunUntilIdle();
189 }
190
191 void OfflinePageTabHelperTest::SimulateHasNetworkConnectivity(bool online) {
192 network_change_notifier_->set_online(online);
193 }
194
195 void OfflinePageTabHelperTest::StartLoad(const GURL& url) {
196 controller().LoadURL(url, content::Referrer(), ui::PAGE_TRANSITION_TYPED,
197 std::string());
198 content::RenderFrameHostTester::For(main_rfh())->
199 SimulateNavigationStart(url);
200 }
201
202 void OfflinePageTabHelperTest::FailLoad(const GURL& url) {
203 content::RenderFrameHostTester::For(main_rfh())->SimulateNavigationStart(url);
204 // Set up the error code for the failed navigation.
205 content::RenderFrameHostTester::For(main_rfh())->
206 SimulateNavigationError(url, net::ERR_INTERNET_DISCONNECTED);
207 content::RenderFrameHostTester::For(main_rfh())->
208 SimulateNavigationErrorPageCommit();
209 // Gives a chance to run delayed task to do redirection.
210 RunUntilIdle();
211 }
212
213 std::unique_ptr<OfflinePageTestArchiver>
214 OfflinePageTabHelperTest::BuildArchiver(const GURL& url,
215 const base::FilePath& file_name) {
216 std::unique_ptr<OfflinePageTestArchiver> archiver(new OfflinePageTestArchiver(
217 this, url, OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED,
218 kTestTitle, kTestFileSize, base::ThreadTaskRunnerHandle::Get()));
219 archiver->set_filename(file_name);
220 return archiver;
221 }
222
223 void OfflinePageTabHelperTest::OnSavePageDone(SavePageResult result,
224 int64_t offline_id) {
225 OfflinePageModel* model =
226 OfflinePageModelFactory::GetForBrowserContext(browser_context());
227 model->GetPageByOfflineId(offline_id,
228 base::Bind(&OfflinePageTabHelperTest::OnGetPageByOfflineIdDone,
229 AsWeakPtr()));
230 }
231
232 void OfflinePageTabHelperTest::SetLastPathCreatedByArchiver(
233 const base::FilePath& file_path) {}
234
235 void OfflinePageTabHelperTest::OnGetPageByOfflineIdDone(
236 const OfflinePageItem* result) {
237 DCHECK(result);
238 offline_page_item_.reset(new OfflinePageItem(*result));
239 }
240
241 TEST_F(OfflinePageTabHelperTest, SwitchToOnlineFromOfflineOnNetwork) {
242 SimulateHasNetworkConnectivity(true);
243
244 StartLoad(offline_url());
245 // Gives a chance to run delayed task to do redirection.
246 RunUntilIdle();
247 // Redirection will be done immediately on navigation start.
248 EXPECT_EQ(online_url(), controller().GetPendingEntry()->GetURL());
249 histograms().ExpectUniqueSample(
250 kRedirectResultHistogram,
251 static_cast<int>(OfflinePageTabHelper::RedirectResult::
252 REDIRECTED_ON_CONNECTED_NETWORK),
253 1);
254 }
255
256 TEST_F(OfflinePageTabHelperTest, SwitchToOfflineFromOnlineOnNoNetwork) {
257 SimulateHasNetworkConnectivity(false);
258
259 StartLoad(online_url());
260 // Gives a chance to run delayed task to do redirection.
261 RunUntilIdle();
262 // Redirection will be done immediately on navigation start.
263 EXPECT_EQ(offline_url(), controller().GetPendingEntry()->GetURL());
264 histograms().ExpectUniqueSample(
265 kRedirectResultHistogram,
266 static_cast<int>(OfflinePageTabHelper::RedirectResult::
267 REDIRECTED_ON_DISCONNECTED_NETWORK),
268 1);
269 }
270
271 TEST_F(OfflinePageTabHelperTest, TestCurrentOfflinePage) {
272 SimulateHasNetworkConnectivity(false);
273
274 StartLoad(online_url());
275 // Gives a chance to run delayed task to do redirection.
276 RunUntilIdle();
277
278 const OfflinePageItem* item =
279 OfflinePageUtils::GetOfflinePageFromWebContents(web_contents());
280 EXPECT_EQ(offline_url(), item->GetOfflineURL());
281 EXPECT_EQ(online_url(), item->url);
282
283 SimulateHasNetworkConnectivity(true);
284 StartLoad(offline_url());
285 RunUntilIdle();
286 item = OfflinePageUtils::GetOfflinePageFromWebContents(web_contents());
287 EXPECT_EQ(nullptr, item);
288 }
289
290 TEST_F(OfflinePageTabHelperTest, SwitchToOfflineFromOnlineOnError) {
291 SimulateHasNetworkConnectivity(true);
292
293 StartLoad(online_url());
294 RunUntilIdle();
295 EXPECT_EQ(online_url(), controller().GetPendingEntry()->GetURL());
296
297 // Redirection will be done immediately on navigation end with error.
298 FailLoad(online_url());
299 EXPECT_EQ(offline_url(), controller().GetPendingEntry()->GetURL());
300
301 histograms().ExpectUniqueSample(
302 kRedirectResultHistogram,
303 static_cast<int>(OfflinePageTabHelper::RedirectResult::
304 REDIRECTED_ON_FLAKY_NETWORK),
305 1);
306 }
307
308 TEST_F(OfflinePageTabHelperTest, NewNavigationCancelsPendingRedirects) {
309 SimulateHasNetworkConnectivity(false);
310
311 StartLoad(online_url());
312 const GURL unsaved_url("http://test.org/page2");
313
314 // We should have a pending task that will do the redirect.
315 ASSERT_TRUE(offline_page_tab_helper()->weak_ptr_factory_.HasWeakPtrs());
316 ASSERT_EQ(online_url(), controller().GetPendingEntry()->GetURL());
317
318 // Should cancel pending tasks for previous URL.
319 StartLoad(unsaved_url);
320
321 // Gives a chance to run delayed task to do redirection.
322 RunUntilIdle();
323
324 // Redirection should be cancelled so we should still navigate to
325 // |unsaved_url|.
326 EXPECT_EQ(unsaved_url, controller().GetPendingEntry()->GetURL());
327
328 // Should report attempt of redirect, but the page not found.
329 histograms().ExpectUniqueSample(
330 kRedirectResultHistogram,
331 static_cast<int>(OfflinePageTabHelper::RedirectResult::
332 PAGE_NOT_FOUND_ON_DISCONNECTED_NETWORK),
333 1);
334 }
335
336 // This test saves 3 pages (one in setup and 2 in test). The most appropriate
337 // test is related to |kTabId|, as it is saved in the latest moment and can be
338 // used in the current tab.
339 TEST_F(OfflinePageTabHelperTest, SelectBestPageForCurrentTab) {
340 // Saves an offline page.
341 OfflinePageModel* model =
342 OfflinePageModelFactory::GetForBrowserContext(browser_context());
343 std::unique_ptr<OfflinePageTestArchiver> archiver(BuildArchiver(
344 kTestPageUrl, base::FilePath(FILE_PATH_LITERAL("page2.mhtml"))));
345
346 // We expect this copy to be used later.
347 ClientId client_id(kLastNNamespace, base::IntToString(kTabId));
348 model->SavePage(
349 kTestPageUrl, client_id, 0l, std::move(archiver),
350 base::Bind(&OfflinePageTabHelperTest::OnSavePageDone, AsWeakPtr()));
351 RunUntilIdle();
352 const int64_t expected_offline_id = offline_id();
353 const GURL expected_offline_url = offline_url();
354
355 archiver = BuildArchiver(kTestPageUrl,
356 base::FilePath(FILE_PATH_LITERAL("page3.html")));
357 client_id.id = "39";
358 model->SavePage(
359 kTestPageUrl, client_id, 0l, std::move(archiver),
360 base::Bind(&OfflinePageTabHelperTest::OnSavePageDone, AsWeakPtr()));
361 RunUntilIdle();
362
363 SimulateHasNetworkConnectivity(false);
364 StartLoad(kTestPageUrl);
365 // Gives a chance to run delayed task to do redirection.
366 RunUntilIdle();
367
368 const OfflinePageItem* item =
369 OfflinePageUtils::GetOfflinePageFromWebContents(web_contents());
370 EXPECT_EQ(expected_offline_id, item->offline_id);
371 EXPECT_EQ(expected_offline_url, item->GetOfflineURL());
372 EXPECT_EQ(kLastNNamespace, item->client_id.name_space);
373 EXPECT_EQ(base::IntToString(kTabId), item->client_id.id);
374 EXPECT_FALSE(offline_page_tab_helper()->is_offline_preview());
375 }
376
377 TEST_F(OfflinePageTabHelperTest, PageFor2GSlow) {
378 SimulateHasNetworkConnectivity(true);
379 TestingProfile* test_profile = profile();
380 UINetworkQualityEstimatorService* nqe_service =
381 UINetworkQualityEstimatorServiceFactory::GetForProfile(test_profile);
382 nqe_service->SetEffectiveConnectionTypeForTesting(
383 net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
384
385 clock()->SetNow(base::Time::Now());
386
387 StartLoad(kTestPageUrl);
388 // Gives a chance to run delayed task to do redirection.
389 RunUntilIdle();
390
391 // This is not included in the field trial, so it should not cause a redirect.
392 const OfflinePageItem* item =
393 OfflinePageUtils::GetOfflinePageFromWebContents(web_contents());
394 EXPECT_FALSE(item);
395
396 base::FieldTrialList field_trial_list(nullptr);
397 ASSERT_TRUE(previews::EnableOfflinePreviewsForTesting());
398
399 StartLoad(kTestPageUrl);
400 // Gives a chance to run delayed task to do redirection.
401 RunUntilIdle();
402
403 // This page should be fresh enough to cause a redirect.
404 item = OfflinePageUtils::GetOfflinePageFromWebContents(web_contents());
405 EXPECT_EQ(offline_url(), item->GetOfflineURL());
406 EXPECT_EQ(online_url(), item->url);
407
408 EXPECT_TRUE(offline_page_tab_helper()->is_offline_preview());
409
410 clock()->Advance(base::TimeDelta::FromDays(8));
411 StartLoad(kTestPageUrl);
412 // Gives a chance to run delayed task to do redirection.
413 RunUntilIdle();
414
415 // This page should not be fresh enough to cause a redirect.
416 item = OfflinePageUtils::GetOfflinePageFromWebContents(web_contents());
417 EXPECT_EQ(nullptr, item);
418 EXPECT_FALSE(offline_page_tab_helper()->is_offline_preview());
419 }
420
421 // This test saves another copy of page from Async Loading namespace
422 // and verifies it is redirected to it (as it is more recent).
423 TEST_F(OfflinePageTabHelperTest, SwitchToOfflineAsyncLoadedPageOnNoNetwork) {
424 // Saves an offline page.
425 OfflinePageModel* model =
426 OfflinePageModelFactory::GetForBrowserContext(browser_context());
427 std::unique_ptr<OfflinePageTestArchiver> archiver(BuildArchiver(
428 kTestPageUrl,
429 base::FilePath(FILE_PATH_LITERAL("AsyncLoadedPage.mhtml"))));
430
431 // We expect this Async Loading Namespace copy to be used.
432 ClientId client_id(kAsyncNamespace, base::IntToString(kTabId));
433 model->SavePage(
434 kTestPageUrl, client_id, 0l, std::move(archiver),
435 base::Bind(&OfflinePageTabHelperTest::OnSavePageDone, AsWeakPtr()));
436 RunUntilIdle();
437 const int64_t expected_offline_id = offline_id();
438 const GURL expected_offline_url = offline_url();
439
440 SimulateHasNetworkConnectivity(false);
441 StartLoad(kTestPageUrl);
442 // Gives a chance to run delayed task to do redirection.
443 RunUntilIdle();
444
445 const OfflinePageItem* item =
446 OfflinePageUtils::GetOfflinePageFromWebContents(web_contents());
447 EXPECT_EQ(expected_offline_id, item->offline_id);
448 EXPECT_EQ(expected_offline_url, item->GetOfflineURL());
449 EXPECT_EQ(kAsyncNamespace, item->client_id.name_space);
450 EXPECT_FALSE(offline_page_tab_helper()->is_offline_preview());
451 }
452
453 } // namespace offline_pages
OLDNEW
« no previous file with comments | « chrome/browser/android/offline_pages/offline_page_bridge.cc ('k') | chrome/browser/android/offline_pages/offline_page_utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698