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 "content/public/test/test_navigation_observer.h"
6
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "base/stl_util.h"
11 #include "content/browser/web_contents/web_contents_impl.h"
12 #include "content/public/browser/web_contents_observer.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace content {
16
17 class TestNavigationObserver::TestWebContentsObserver
18 : public WebContentsObserver {
19 public:
TestWebContentsObserver(TestNavigationObserver * parent,WebContents * web_contents)20 TestWebContentsObserver(TestNavigationObserver* parent,
21 WebContents* web_contents)
22 : WebContentsObserver(web_contents),
23 parent_(parent) {
24 }
25
26 private:
27 // WebContentsObserver:
NavigationEntryCommitted(const LoadCommittedDetails & load_details)28 virtual void NavigationEntryCommitted(
29 const LoadCommittedDetails& load_details) OVERRIDE {
30 parent_->OnNavigationEntryCommitted(this, web_contents(), load_details);
31 }
32
DidAttachInterstitialPage()33 virtual void DidAttachInterstitialPage() OVERRIDE {
34 parent_->OnDidAttachInterstitialPage(web_contents());
35 }
36
WebContentsDestroyed()37 virtual void WebContentsDestroyed() OVERRIDE {
38 parent_->OnWebContentsDestroyed(this, web_contents());
39 }
40
DidStartLoading(RenderViewHost * render_view_host)41 virtual void DidStartLoading(RenderViewHost* render_view_host) OVERRIDE {
42 parent_->OnDidStartLoading(web_contents());
43 }
44
DidStopLoading(RenderViewHost * render_view_host)45 virtual void DidStopLoading(RenderViewHost* render_view_host) OVERRIDE {
46 parent_->OnDidStopLoading(web_contents());
47 }
48
49 TestNavigationObserver* parent_;
50
51 DISALLOW_COPY_AND_ASSIGN(TestWebContentsObserver);
52 };
53
TestNavigationObserver(WebContents * web_contents,int number_of_navigations)54 TestNavigationObserver::TestNavigationObserver(
55 WebContents* web_contents,
56 int number_of_navigations)
57 : navigation_started_(false),
58 navigations_completed_(0),
59 number_of_navigations_(number_of_navigations),
60 message_loop_runner_(new MessageLoopRunner),
61 web_contents_created_callback_(
62 base::Bind(
63 &TestNavigationObserver::OnWebContentsCreated,
64 base::Unretained(this))) {
65 if (web_contents)
66 RegisterAsObserver(web_contents);
67 }
68
TestNavigationObserver(WebContents * web_contents)69 TestNavigationObserver::TestNavigationObserver(
70 WebContents* web_contents)
71 : navigation_started_(false),
72 navigations_completed_(0),
73 number_of_navigations_(1),
74 message_loop_runner_(new MessageLoopRunner),
75 web_contents_created_callback_(
76 base::Bind(
77 &TestNavigationObserver::OnWebContentsCreated,
78 base::Unretained(this))) {
79 if (web_contents)
80 RegisterAsObserver(web_contents);
81 }
82
~TestNavigationObserver()83 TestNavigationObserver::~TestNavigationObserver() {
84 StopWatchingNewWebContents();
85
86 STLDeleteContainerPointers(web_contents_observers_.begin(),
87 web_contents_observers_.end());
88 }
89
Wait()90 void TestNavigationObserver::Wait() {
91 message_loop_runner_->Run();
92 }
93
StartWatchingNewWebContents()94 void TestNavigationObserver::StartWatchingNewWebContents() {
95 WebContentsImpl::AddCreatedCallback(web_contents_created_callback_);
96 }
97
StopWatchingNewWebContents()98 void TestNavigationObserver::StopWatchingNewWebContents() {
99 WebContentsImpl::RemoveCreatedCallback(web_contents_created_callback_);
100 }
101
RegisterAsObserver(WebContents * web_contents)102 void TestNavigationObserver::RegisterAsObserver(WebContents* web_contents) {
103 web_contents_observers_.insert(
104 new TestWebContentsObserver(this, web_contents));
105 }
106
OnWebContentsCreated(WebContents * web_contents)107 void TestNavigationObserver::OnWebContentsCreated(WebContents* web_contents) {
108 RegisterAsObserver(web_contents);
109 }
110
OnWebContentsDestroyed(TestWebContentsObserver * observer,WebContents * web_contents)111 void TestNavigationObserver::OnWebContentsDestroyed(
112 TestWebContentsObserver* observer,
113 WebContents* web_contents) {
114 web_contents_observers_.erase(observer);
115 delete observer;
116 }
117
OnNavigationEntryCommitted(TestWebContentsObserver * observer,WebContents * web_contents,const LoadCommittedDetails & load_details)118 void TestNavigationObserver::OnNavigationEntryCommitted(
119 TestWebContentsObserver* observer,
120 WebContents* web_contents,
121 const LoadCommittedDetails& load_details) {
122 navigation_started_ = true;
123 }
124
OnDidAttachInterstitialPage(WebContents * web_contents)125 void TestNavigationObserver::OnDidAttachInterstitialPage(
126 WebContents* web_contents) {
127 // Going to an interstitial page does not trigger NavigationEntryCommitted,
128 // but has the same meaning for us here.
129 navigation_started_ = true;
130 }
131
OnDidStartLoading(WebContents * web_contents)132 void TestNavigationObserver::OnDidStartLoading(WebContents* web_contents) {
133 navigation_started_ = true;
134 }
135
OnDidStopLoading(WebContents * web_contents)136 void TestNavigationObserver::OnDidStopLoading(WebContents* web_contents) {
137 if (!navigation_started_)
138 return;
139
140 ++navigations_completed_;
141 if (navigations_completed_ == number_of_navigations_) {
142 navigation_started_ = false;
143 message_loop_runner_->Quit();
144 }
145 }
146
147 } // namespace content
148