[Android] Implement 3-way sensor fallback for Device Orientation.
[chromium-blink-merge.git] / content / public / test / test_utils.cc
blobf833582aa756176ff969fcf8eff7dab97c5a76c1
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.
5 #include "content/public/test/test_utils.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/location.h"
10 #include "base/run_loop.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "base/values.h"
15 #include "content/public/browser/browser_child_process_host_iterator.h"
16 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/render_frame_host.h"
18 #include "content/public/browser/render_process_host.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/common/content_switches.h"
21 #include "content/public/common/process_type.h"
22 #include "content/public/test/test_launcher.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 namespace content {
27 namespace {
29 // Number of times to repost a Quit task so that the MessageLoop finishes up
30 // pending tasks and tasks posted by those pending tasks without risking the
31 // potential hang behavior of MessageLoop::QuitWhenIdle.
32 // The criteria for choosing this number: it should be high enough to make the
33 // quit act like QuitWhenIdle, while taking into account that any page which is
34 // animating may be rendering another frame for each quit deferral. For an
35 // animating page, the potential delay to quitting the RunLoop would be
36 // kNumQuitDeferrals * frame_render_time. Some perf tests run slow, such as
37 // 200ms/frame.
38 static const int kNumQuitDeferrals = 10;
40 static void DeferredQuitRunLoop(const base::Closure& quit_task,
41 int num_quit_deferrals) {
42 if (num_quit_deferrals <= 0) {
43 quit_task.Run();
44 } else {
45 base::ThreadTaskRunnerHandle::Get()->PostTask(
46 FROM_HERE,
47 base::Bind(&DeferredQuitRunLoop, quit_task, num_quit_deferrals - 1));
51 void RunAllPendingMessageAndSendQuit(BrowserThread::ID thread_id,
52 const base::Closure& quit_task) {
53 RunAllPendingInMessageLoop();
54 BrowserThread::PostTask(thread_id, FROM_HERE, quit_task);
57 // Class used to handle result callbacks for ExecuteScriptAndGetValue.
58 class ScriptCallback {
59 public:
60 ScriptCallback() { }
61 virtual ~ScriptCallback() { }
62 void ResultCallback(const base::Value* result);
64 scoped_ptr<base::Value> result() { return result_.Pass(); }
66 private:
67 scoped_ptr<base::Value> result_;
69 DISALLOW_COPY_AND_ASSIGN(ScriptCallback);
72 void ScriptCallback::ResultCallback(const base::Value* result) {
73 if (result)
74 result_.reset(result->DeepCopy());
75 base::MessageLoop::current()->Quit();
78 // Monitors if any task is processed by the message loop.
79 class TaskObserver : public base::MessageLoop::TaskObserver {
80 public:
81 TaskObserver() : processed_(false) {}
82 ~TaskObserver() override {}
84 // MessageLoop::TaskObserver overrides.
85 void WillProcessTask(const base::PendingTask& pending_task) override {}
86 void DidProcessTask(const base::PendingTask& pending_task) override {
87 processed_ = true;
90 // Returns true if any task was processed.
91 bool processed() const { return processed_; }
93 private:
94 bool processed_;
95 DISALLOW_COPY_AND_ASSIGN(TaskObserver);
98 // Adapter that makes a WindowedNotificationObserver::ConditionTestCallback from
99 // a WindowedNotificationObserver::ConditionTestCallbackWithoutSourceAndDetails
100 // by ignoring the notification source and details.
101 bool IgnoreSourceAndDetails(
102 const WindowedNotificationObserver::
103 ConditionTestCallbackWithoutSourceAndDetails& callback,
104 const NotificationSource& source,
105 const NotificationDetails& details) {
106 return callback.Run();
109 } // namespace
111 void RunMessageLoop() {
112 base::RunLoop run_loop;
113 RunThisRunLoop(&run_loop);
116 void RunThisRunLoop(base::RunLoop* run_loop) {
117 base::MessageLoop::ScopedNestableTaskAllower allow(
118 base::MessageLoop::current());
120 // If we're running inside a browser test, we might need to allow the test
121 // launcher to do extra work before/after running a nested message loop.
122 TestLauncherDelegate* delegate = NULL;
123 #if !defined(OS_IOS)
124 delegate = GetCurrentTestLauncherDelegate();
125 #endif
126 if (delegate)
127 delegate->PreRunMessageLoop(run_loop);
128 run_loop->Run();
129 if (delegate)
130 delegate->PostRunMessageLoop();
133 void RunAllPendingInMessageLoop() {
134 base::RunLoop run_loop;
135 base::ThreadTaskRunnerHandle::Get()->PostTask(
136 FROM_HERE, GetQuitTaskForRunLoop(&run_loop));
137 RunThisRunLoop(&run_loop);
140 void RunAllPendingInMessageLoop(BrowserThread::ID thread_id) {
141 if (BrowserThread::CurrentlyOn(thread_id)) {
142 RunAllPendingInMessageLoop();
143 return;
145 BrowserThread::ID current_thread_id;
146 if (!BrowserThread::GetCurrentThreadIdentifier(&current_thread_id)) {
147 NOTREACHED();
148 return;
151 base::RunLoop run_loop;
152 BrowserThread::PostTask(thread_id, FROM_HERE,
153 base::Bind(&RunAllPendingMessageAndSendQuit, current_thread_id,
154 run_loop.QuitClosure()));
155 RunThisRunLoop(&run_loop);
158 void RunAllBlockingPoolTasksUntilIdle() {
159 while (true) {
160 content::BrowserThread::GetBlockingPool()->FlushForTesting();
162 TaskObserver task_observer;
163 base::MessageLoop::current()->AddTaskObserver(&task_observer);
164 base::RunLoop().RunUntilIdle();
165 base::MessageLoop::current()->RemoveTaskObserver(&task_observer);
167 if (!task_observer.processed())
168 break;
172 base::Closure GetQuitTaskForRunLoop(base::RunLoop* run_loop) {
173 return base::Bind(&DeferredQuitRunLoop, run_loop->QuitClosure(),
174 kNumQuitDeferrals);
177 scoped_ptr<base::Value> ExecuteScriptAndGetValue(
178 RenderFrameHost* render_frame_host, const std::string& script) {
179 ScriptCallback observer;
181 render_frame_host->ExecuteJavaScriptForTests(
182 base::UTF8ToUTF16(script),
183 base::Bind(&ScriptCallback::ResultCallback, base::Unretained(&observer)));
184 base::MessageLoop* loop = base::MessageLoop::current();
185 loop->Run();
186 return observer.result().Pass();
189 bool AreAllSitesIsolatedForTesting() {
190 return base::CommandLine::ForCurrentProcess()->HasSwitch(
191 switches::kSitePerProcess);
194 void IsolateAllSitesForTesting(base::CommandLine* command_line) {
195 command_line->AppendSwitch(switches::kSitePerProcess);
198 MessageLoopRunner::MessageLoopRunner()
199 : loop_running_(false),
200 quit_closure_called_(false) {
203 MessageLoopRunner::~MessageLoopRunner() {
206 void MessageLoopRunner::Run() {
207 // Do not run the message loop if our quit closure has already been called.
208 // This helps in scenarios where the closure has a chance to run before
209 // we Run explicitly.
210 if (quit_closure_called_)
211 return;
213 loop_running_ = true;
214 RunThisRunLoop(&run_loop_);
217 base::Closure MessageLoopRunner::QuitClosure() {
218 return base::Bind(&MessageLoopRunner::Quit, this);
221 void MessageLoopRunner::Quit() {
222 quit_closure_called_ = true;
224 // Only run the quit task if we are running the message loop.
225 if (loop_running_) {
226 GetQuitTaskForRunLoop(&run_loop_).Run();
227 loop_running_ = false;
231 WindowedNotificationObserver::WindowedNotificationObserver(
232 int notification_type,
233 const NotificationSource& source)
234 : seen_(false),
235 running_(false),
236 source_(NotificationService::AllSources()) {
237 AddNotificationType(notification_type, source);
240 WindowedNotificationObserver::WindowedNotificationObserver(
241 int notification_type,
242 const ConditionTestCallback& callback)
243 : seen_(false),
244 running_(false),
245 callback_(callback),
246 source_(NotificationService::AllSources()) {
247 AddNotificationType(notification_type, source_);
250 WindowedNotificationObserver::WindowedNotificationObserver(
251 int notification_type,
252 const ConditionTestCallbackWithoutSourceAndDetails& callback)
253 : seen_(false),
254 running_(false),
255 callback_(base::Bind(&IgnoreSourceAndDetails, callback)),
256 source_(NotificationService::AllSources()) {
257 registrar_.Add(this, notification_type, source_);
260 WindowedNotificationObserver::~WindowedNotificationObserver() {}
262 void WindowedNotificationObserver::AddNotificationType(
263 int notification_type,
264 const NotificationSource& source) {
265 registrar_.Add(this, notification_type, source);
268 void WindowedNotificationObserver::Wait() {
269 if (seen_)
270 return;
272 running_ = true;
273 message_loop_runner_ = new MessageLoopRunner;
274 message_loop_runner_->Run();
275 EXPECT_TRUE(seen_);
278 void WindowedNotificationObserver::Observe(
279 int type,
280 const NotificationSource& source,
281 const NotificationDetails& details) {
282 source_ = source;
283 details_ = details;
284 if (!callback_.is_null() && !callback_.Run(source, details))
285 return;
287 seen_ = true;
288 if (!running_)
289 return;
291 message_loop_runner_->Quit();
292 running_ = false;
295 InProcessUtilityThreadHelper::InProcessUtilityThreadHelper()
296 : child_thread_count_(0) {
297 RenderProcessHost::SetRunRendererInProcess(true);
298 BrowserChildProcessObserver::Add(this);
301 InProcessUtilityThreadHelper::~InProcessUtilityThreadHelper() {
302 if (child_thread_count_) {
303 DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::UI));
304 DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::IO));
305 runner_ = new MessageLoopRunner;
306 runner_->Run();
308 BrowserChildProcessObserver::Remove(this);
309 RenderProcessHost::SetRunRendererInProcess(false);
312 void InProcessUtilityThreadHelper::BrowserChildProcessHostConnected(
313 const ChildProcessData& data) {
314 child_thread_count_++;
317 void InProcessUtilityThreadHelper::BrowserChildProcessHostDisconnected(
318 const ChildProcessData& data) {
319 if (--child_thread_count_)
320 return;
322 if (runner_.get())
323 runner_->Quit();
326 RenderFrameDeletedObserver::RenderFrameDeletedObserver(RenderFrameHost* rfh)
327 : WebContentsObserver(WebContents::FromRenderFrameHost(rfh)),
328 process_id_(rfh->GetProcess()->GetID()),
329 routing_id_(rfh->GetRoutingID()),
330 deleted_(false) {}
332 RenderFrameDeletedObserver::~RenderFrameDeletedObserver() {}
334 void RenderFrameDeletedObserver::RenderFrameDeleted(
335 RenderFrameHost* render_frame_host) {
336 if (render_frame_host->GetProcess()->GetID() == process_id_ &&
337 render_frame_host->GetRoutingID() == routing_id_) {
338 deleted_ = true;
340 if (runner_.get())
341 runner_->Quit();
345 bool RenderFrameDeletedObserver::deleted() {
346 return deleted_;
349 void RenderFrameDeletedObserver::WaitUntilDeleted() {
350 if (deleted_)
351 return;
353 runner_.reset(new base::RunLoop());
354 runner_->Run();
355 runner_.reset();
358 WebContentsDestroyedWatcher::WebContentsDestroyedWatcher(
359 WebContents* web_contents)
360 : WebContentsObserver(web_contents),
361 message_loop_runner_(new MessageLoopRunner) {
362 EXPECT_TRUE(web_contents != NULL);
365 WebContentsDestroyedWatcher::~WebContentsDestroyedWatcher() {}
367 void WebContentsDestroyedWatcher::Wait() {
368 message_loop_runner_->Run();
371 void WebContentsDestroyedWatcher::WebContentsDestroyed() {
372 message_loop_runner_->Quit();
375 } // namespace content