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 <stdarg.h> 6 #include <string.h> 7 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" 16 17 namespace { 18 19 struct RunState { 20 RunState(base::MessagePump::Delegate* delegate, int run_depth) 21 : delegate(delegate), 22 run_depth(run_depth), 23 should_quit(false) { 24 } 25 26 base::MessagePump::Delegate* delegate; 27 28 // Used to count how many Run() invocations are on the stack. 29 int run_depth; 30 31 // Used to flag that the current Run() invocation should return ASAP. 32 bool should_quit; 33 }; 34 35 RunState* g_state = NULL; 36 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. 40 class Waitable { 41 public: 42 static Waitable* GetInstance() { 43 return Singleton<Waitable>::get(); 44 } 45 46 // Signals that there are more work to do. 47 void Signal() { 48 waitable_event_.Signal(); 49 } 50 51 // Blocks until more work is scheduled. 52 void Block() { 53 waitable_event_.Wait(); 54 } 55 56 void Quit() { 57 g_state->should_quit = true; 58 Signal(); 59 } 60 61 private: 62 friend struct DefaultSingletonTraits<Waitable>; 63 64 Waitable() 65 : waitable_event_(false, false) { 66 } 67 68 base::WaitableEvent waitable_event_; 69 70 DISALLOW_COPY_AND_ASSIGN(Waitable); 71 }; 72 73 // The MessagePumpForUI implementation for test purpose. 74 class MessagePumpForUIStub : public base::MessagePumpForUI { 75 virtual ~MessagePumpForUIStub() {} 76 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."; 80 } 81 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); 86 87 RunState* previous_state = g_state; 88 g_state = &state; 89 90 bool more_work_is_plausible = true; 91 92 for (;;) { 93 if (!more_work_is_plausible) { 94 Waitable::GetInstance()->Block(); 95 if (g_state->should_quit) 96 break; 97 } 98 99 more_work_is_plausible = g_state->delegate->DoWork(); 100 if (g_state->should_quit) 101 break; 102 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) 107 break; 108 109 if (more_work_is_plausible) 110 continue; 111 112 more_work_is_plausible = g_state->delegate->DoIdleWork(); 113 if (g_state->should_quit) 114 break; 115 116 more_work_is_plausible |= !delayed_work_time.is_null(); 117 } 118 119 g_state = previous_state; 120 } 121 122 virtual void Quit() OVERRIDE { 123 Waitable::GetInstance()->Quit(); 124 } 125 126 virtual void ScheduleWork() OVERRIDE { 127 Waitable::GetInstance()->Signal(); 128 } 129 130 virtual void ScheduleDelayedWork( 131 const base::TimeTicks& delayed_work_time) OVERRIDE { 132 Waitable::GetInstance()->Signal(); 133 } 134 }; 135 136 base::MessagePump* CreateMessagePumpForUIStub() { 137 return new MessagePumpForUIStub(); 138 }; 139 140 // Provides the test path for DIR_MODULE and DIR_ANDROID_APP_DATA. 141 bool GetTestProviderPath(int key, base::FilePath* result) { 142 switch (key) { 143 case base::DIR_MODULE: { 144 return base::android::GetExternalStorageDirectory(result); 145 } 146 case base::DIR_ANDROID_APP_DATA: { 147 // For tests, app data is put in external storage. 148 return base::android::GetExternalStorageDirectory(result); 149 } 150 default: 151 return false; 152 } 153 } 154 155 void InitPathProvider(int key) { 156 base::FilePath path; 157 // If failed to override the key, that means the way has not been registered. 158 if (GetTestProviderPath(key, &path) && !PathService::Override(key, path)) 159 PathService::RegisterProvider(&GetTestProviderPath, key, key + 1); 160 } 161 162 } // namespace 163 164 namespace base { 165 166 void InitAndroidTestLogging() { 167 logging::LoggingSettings settings; 168 settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; 169 logging::InitLogging(settings); 170 // To view log output with IDs and timestamps use "adb logcat -v threadtime". 171 logging::SetLogItems(false, // Process ID 172 false, // Thread ID 173 false, // Timestamp 174 false); // Tick count 175 } 176 177 void InitAndroidTestPaths() { 178 InitPathProvider(DIR_MODULE); 179 InitPathProvider(DIR_ANDROID_APP_DATA); 180 } 181 182 void InitAndroidTestMessageLoop() { 183 if (!MessageLoop::InitMessagePumpForUIFactory(&CreateMessagePumpForUIStub)) 184 LOG(INFO) << "MessagePumpForUIFactory already set, unable to override."; 185 } 186 187 void InitAndroidTest() { 188 InitAndroidTestLogging(); 189 InitAndroidTestPaths(); 190 InitAndroidTestMessageLoop(); 191 } 192 } // namespace base 193