test_navigation_observer.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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.h"
9#include "base/run_loop.h"
10#include "content/public/browser/notification_service.h"
11#include "content/public/browser/notification_types.h"
12#include "content/public/browser/render_view_host_observer.h"
13#include "content/public/test/js_injection_ready_observer.h"
14#include "content/public/test/test_utils.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17namespace content {
18
19// This class observes |render_view_host| and calls OnJsInjectionReady() of
20// |js_injection_ready_observer| when the time is right to inject JavaScript
21// into the page.
22class TestNavigationObserver::RVHOSendJS : public RenderViewHostObserver {
23 public:
24  RVHOSendJS(RenderViewHost* render_view_host,
25             JsInjectionReadyObserver* js_injection_ready_observer)
26      : RenderViewHostObserver(render_view_host),
27        js_injection_ready_observer_(js_injection_ready_observer) {
28  }
29
30 private:
31  // RenderViewHostObserver implementation.
32  virtual void RenderViewHostInitialized() OVERRIDE {
33    if (js_injection_ready_observer_)
34      js_injection_ready_observer_->OnJsInjectionReady(render_view_host());
35  }
36
37  JsInjectionReadyObserver* js_injection_ready_observer_;
38
39  DISALLOW_COPY_AND_ASSIGN(RVHOSendJS);
40};
41
42TestNavigationObserver::TestNavigationObserver(
43    const NotificationSource& source,
44    JsInjectionReadyObserver* js_injection_ready_observer,
45    int number_of_navigations)
46    : navigation_started_(false),
47      navigations_completed_(0),
48      number_of_navigations_(number_of_navigations),
49      js_injection_ready_observer_(js_injection_ready_observer),
50      done_(false),
51      running_(false) {
52  // When javascript injection is requested, register for RenderViewHost
53  // creation.
54  if (js_injection_ready_observer_) {
55    registrar_.Add(this, NOTIFICATION_RENDER_VIEW_HOST_CREATED,
56                   NotificationService::AllSources());
57  }
58  RegisterAsObserver(source);
59}
60
61TestNavigationObserver::TestNavigationObserver(
62    const NotificationSource& source)
63    : navigation_started_(false),
64      navigations_completed_(0),
65      number_of_navigations_(1),
66      js_injection_ready_observer_(NULL),
67      done_(false),
68      running_(false) {
69  RegisterAsObserver(source);
70}
71
72TestNavigationObserver::~TestNavigationObserver() {
73}
74
75void TestNavigationObserver::WaitForObservation(
76    const base::Closure& wait_loop_callback,
77    const base::Closure& done_callback) {
78  if (done_)
79    return;
80
81  EXPECT_FALSE(running_);
82  running_ = true;
83  done_callback_ = done_callback;
84  wait_loop_callback.Run();
85  EXPECT_TRUE(done_);
86}
87
88void TestNavigationObserver::Wait() {
89  base::RunLoop run_loop;
90  WaitForObservation(
91      base::Bind(&base::RunLoop::Run, base::Unretained(&run_loop)),
92      GetQuitTaskForRunLoop(&run_loop));
93}
94
95TestNavigationObserver::TestNavigationObserver(
96    JsInjectionReadyObserver* js_injection_ready_observer,
97    int number_of_navigations)
98    : navigation_started_(false),
99      navigations_completed_(0),
100      number_of_navigations_(number_of_navigations),
101      js_injection_ready_observer_(js_injection_ready_observer),
102      done_(false),
103      running_(false) {
104  // When javascript injection is requested, register for RenderViewHost
105  // creation.
106  if (js_injection_ready_observer_) {
107    registrar_.Add(this, NOTIFICATION_RENDER_VIEW_HOST_CREATED,
108                   NotificationService::AllSources());
109  }
110}
111
112void TestNavigationObserver::RegisterAsObserver(
113    const NotificationSource& source) {
114  // Register for events to know when we've finished loading the page and are
115  // ready to quit the current message loop to return control back to the
116  // waiting test.
117  registrar_.Add(this, NOTIFICATION_NAV_ENTRY_COMMITTED, source);
118  registrar_.Add(this, NOTIFICATION_LOAD_START, source);
119  registrar_.Add(this, NOTIFICATION_LOAD_STOP, source);
120}
121
122void TestNavigationObserver::Observe(
123    int type, const NotificationSource& source,
124    const NotificationDetails& details) {
125  switch (type) {
126    case NOTIFICATION_NAV_ENTRY_COMMITTED:
127    case NOTIFICATION_LOAD_START:
128      navigation_started_ = true;
129      break;
130    case NOTIFICATION_LOAD_STOP:
131      if (navigation_started_ &&
132          ++navigations_completed_ == number_of_navigations_) {
133        navigation_started_ = false;
134        done_ = true;
135        if (running_) {
136          running_ = false;
137          done_callback_.Run();
138        }
139      }
140      break;
141    case NOTIFICATION_RENDER_VIEW_HOST_CREATED:
142      rvho_send_js_.reset(new RVHOSendJS(
143          Source<RenderViewHost>(source).ptr(),
144          js_injection_ready_observer_));
145      break;
146    default:
147      NOTREACHED();
148  }
149}
150
151}  // namespace content
152