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.
8 #include "base/android/path_utils.h"
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "base/memory/singleton.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/message_loop/message_pump_android.h"
14 #include "base/path_service.h"
15 #include "base/synchronization/waitable_event.h"
20 RunState(base::MessagePump::Delegate
* delegate
, int run_depth
)
26 base::MessagePump::Delegate
* delegate
;
28 // Used to count how many Run() invocations are on the stack.
31 // Used to flag that the current Run() invocation should return ASAP.
35 RunState
* g_state
= NULL
;
37 // A singleton WaitableEvent wrapper so we avoid a busy loop in
38 // MessagePumpForUIStub. Other platforms use the native event loop which blocks
39 // when there are no pending messages.
42 static Waitable
* GetInstance() {
43 return Singleton
<Waitable
>::get();
46 // Signals that there are more work to do.
48 waitable_event_
.Signal();
51 // Blocks until more work is scheduled.
53 waitable_event_
.Wait();
57 g_state
->should_quit
= true;
62 friend struct DefaultSingletonTraits
<Waitable
>;
65 : waitable_event_(false, false) {
68 base::WaitableEvent waitable_event_
;
70 DISALLOW_COPY_AND_ASSIGN(Waitable
);
73 // The MessagePumpForUI implementation for test purpose.
74 class MessagePumpForUIStub
: public base::MessagePumpForUI
{
75 virtual ~MessagePumpForUIStub() {}
77 virtual void Start(base::MessagePump::Delegate
* delegate
) override
{
78 NOTREACHED() << "The Start() method shouldn't be called in test, using"
79 " Run() method should be used.";
82 virtual void Run(base::MessagePump::Delegate
* delegate
) override
{
83 // The following was based on message_pump_glib.cc, except we're using a
84 // WaitableEvent since there are no native message loop to use.
85 RunState
state(delegate
, g_state
? g_state
->run_depth
+ 1 : 1);
87 RunState
* previous_state
= g_state
;
90 bool more_work_is_plausible
= true;
93 if (!more_work_is_plausible
) {
94 Waitable::GetInstance()->Block();
95 if (g_state
->should_quit
)
99 more_work_is_plausible
= g_state
->delegate
->DoWork();
100 if (g_state
->should_quit
)
103 base::TimeTicks delayed_work_time
;
104 more_work_is_plausible
|=
105 g_state
->delegate
->DoDelayedWork(&delayed_work_time
);
106 if (g_state
->should_quit
)
109 if (more_work_is_plausible
)
112 more_work_is_plausible
= g_state
->delegate
->DoIdleWork();
113 if (g_state
->should_quit
)
116 more_work_is_plausible
|= !delayed_work_time
.is_null();
119 g_state
= previous_state
;
122 virtual void Quit() override
{
123 Waitable::GetInstance()->Quit();
126 virtual void ScheduleWork() override
{
127 Waitable::GetInstance()->Signal();
130 virtual void ScheduleDelayedWork(
131 const base::TimeTicks
& delayed_work_time
) override
{
132 Waitable::GetInstance()->Signal();
136 scoped_ptr
<base::MessagePump
> CreateMessagePumpForUIStub() {
137 return scoped_ptr
<base::MessagePump
>(new MessagePumpForUIStub());
140 // Provides the test path for DIR_MODULE and DIR_ANDROID_APP_DATA.
141 bool GetTestProviderPath(int key
, base::FilePath
* result
) {
143 case base::DIR_ANDROID_APP_DATA
: {
144 // For tests, app data is put in external storage.
145 return base::android::GetExternalStorageDirectory(result
);
152 void InitPathProvider(int key
) {
154 // If failed to override the key, that means the way has not been registered.
155 if (GetTestProviderPath(key
, &path
) && !PathService::Override(key
, path
))
156 PathService::RegisterProvider(&GetTestProviderPath
, key
, key
+ 1);
163 void InitAndroidTestLogging() {
164 logging::LoggingSettings settings
;
165 settings
.logging_dest
= logging::LOG_TO_SYSTEM_DEBUG_LOG
;
166 logging::InitLogging(settings
);
167 // To view log output with IDs and timestamps use "adb logcat -v threadtime".
168 logging::SetLogItems(false, // Process ID
171 false); // Tick count
174 void InitAndroidTestPaths() {
175 InitPathProvider(DIR_MODULE
);
176 InitPathProvider(DIR_ANDROID_APP_DATA
);
179 void InitAndroidTestMessageLoop() {
180 if (!MessageLoop::InitMessagePumpForUIFactory(&CreateMessagePumpForUIStub
))
181 LOG(INFO
) << "MessagePumpForUIFactory already set, unable to override.";
184 void InitAndroidTest() {
185 InitAndroidTestLogging();
186 InitAndroidTestPaths();
187 InitAndroidTestMessageLoop();