1// Copyright (c) 2012 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/chromeos/offline/offline_load_page.h"
6#include "chrome/test/base/chrome_render_view_host_test_harness.h"
7#include "content/public/browser/interstitial_page.h"
8#include "content/public/browser/navigation_controller.h"
9#include "content/public/browser/web_contents.h"
10#include "content/public/test/web_contents_tester.h"
11
12using content::InterstitialPage;
13using content::WebContents;
14using content::WebContentsTester;
15
16static const char* kURL1 = "http://www.google.com/";
17static const char* kURL2 = "http://www.gmail.com/";
18
19namespace chromeos {
20
21class OfflineLoadPageTest;
22
23// An OfflineLoadPage class that does not create windows.
24class TestOfflineLoadPage :  public chromeos::OfflineLoadPage {
25 public:
26  TestOfflineLoadPage(WebContents* web_contents,
27                      const GURL& url,
28                      OfflineLoadPageTest* test_page)
29    : chromeos::OfflineLoadPage(web_contents, url, CompletionCallback()),
30      test_page_(test_page) {
31    interstitial_page_->DontCreateViewForTesting();
32  }
33
34  // chromeos::OfflineLoadPage override.
35  virtual void NotifyBlockingPageComplete(bool proceed) OVERRIDE;
36
37 private:
38  OfflineLoadPageTest* test_page_;
39
40  DISALLOW_COPY_AND_ASSIGN(TestOfflineLoadPage);
41};
42
43class OfflineLoadPageTest : public ChromeRenderViewHostTestHarness {
44 public:
45  // The decision the user made.
46  enum UserResponse {
47    PENDING,
48    OK,
49    CANCEL
50  };
51
52  virtual void SetUp() {
53    ChromeRenderViewHostTestHarness::SetUp();
54    user_response_ = PENDING;
55  }
56
57  void OnBlockingPageComplete(bool proceed) {
58    if (proceed)
59      user_response_ = OK;
60    else
61      user_response_ = CANCEL;
62  }
63
64  void Navigate(const char* url, int page_id) {
65    WebContentsTester::For(web_contents())->TestDidNavigate(
66        web_contents()->GetMainFrame(), page_id, GURL(url),
67        ui::PAGE_TRANSITION_TYPED);
68  }
69
70  void ShowInterstitial(const char* url) {
71    (new TestOfflineLoadPage(web_contents(), GURL(url), this))->Show();
72  }
73
74  // Returns the OfflineLoadPage currently showing or NULL if none is
75  // showing.
76  InterstitialPage* GetOfflineLoadPage() {
77    return InterstitialPage::GetInterstitialPage(web_contents());
78  }
79
80  UserResponse user_response() const { return user_response_; }
81
82 private:
83  friend class TestOfflineLoadPage;
84
85  UserResponse user_response_;
86};
87
88void TestOfflineLoadPage::NotifyBlockingPageComplete(bool proceed) {
89  test_page_->OnBlockingPageComplete(proceed);
90}
91
92TEST_F(OfflineLoadPageTest, OfflinePageProceed) {
93  // Start a load.
94  Navigate(kURL1, 1);
95  // Load next page.
96  controller().LoadURL(GURL(kURL2), content::Referrer(),
97                       ui::PAGE_TRANSITION_TYPED, std::string());
98
99  // Simulate the load causing an offline browsing interstitial page
100  // to be shown.
101  ShowInterstitial(kURL2);
102  InterstitialPage* interstitial = GetOfflineLoadPage();
103  ASSERT_TRUE(interstitial);
104  base::MessageLoop::current()->RunUntilIdle();
105
106  // Simulate the user clicking "proceed".
107  interstitial->Proceed();
108  base::MessageLoop::current()->RunUntilIdle();
109
110  EXPECT_EQ(OK, user_response());
111
112  // The URL remains to be URL2.
113  EXPECT_EQ(kURL2, web_contents()->GetVisibleURL().spec());
114
115  // Commit navigation and the interstitial page is gone.
116  Navigate(kURL2, 2);
117  EXPECT_FALSE(GetOfflineLoadPage());
118}
119
120// Tests showing an offline page and not proceeding.
121TEST_F(OfflineLoadPageTest, OfflinePageDontProceed) {
122  // Start a load.
123  Navigate(kURL1, 1);
124  controller().LoadURL(GURL(kURL2), content::Referrer(),
125                       ui::PAGE_TRANSITION_TYPED, std::string());
126
127  // Simulate the load causing an offline interstitial page to be shown.
128  ShowInterstitial(kURL2);
129  InterstitialPage* interstitial = GetOfflineLoadPage();
130  ASSERT_TRUE(interstitial);
131  base::MessageLoop::current()->RunUntilIdle();
132
133  // Simulate the user clicking "don't proceed".
134  interstitial->DontProceed();
135
136  // The interstitial should be gone.
137  EXPECT_EQ(CANCEL, user_response());
138  EXPECT_FALSE(GetOfflineLoadPage());
139  // We did not proceed, the pending entry should be gone.
140  EXPECT_FALSE(controller().GetPendingEntry());
141  // the URL is set back to kURL1.
142  EXPECT_EQ(kURL1, web_contents()->GetLastCommittedURL().spec());
143}
144
145}  // namespace chromeos
146