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