OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/test/browser_test_message_pump_android.h" | 5 #include "content/test/browser_test_message_pump_android.h" |
6 | 6 |
| 7 #include "base/android/jni_android.h" |
| 8 #include "base/android/scoped_java_ref.h" |
| 9 #include "base/lazy_instance.h" |
7 #include "base/logging.h" | 10 #include "base/logging.h" |
8 #include "base/synchronization/waitable_event.h" | 11 #include "base/synchronization/waitable_event.h" |
9 #include "base/time.h" | 12 #include "base/time.h" |
| 13 #include "jni/BrowserTestSystemMessageHandler_jni.h" |
| 14 |
| 15 namespace { |
| 16 |
| 17 base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject> > |
| 18 g_message_handler_obj = LAZY_INSTANCE_INITIALIZER; |
| 19 |
| 20 } // namespace |
| 21 |
10 | 22 |
11 namespace content { | 23 namespace content { |
12 | 24 |
13 struct BrowserTestMessagePumpAndroid::RunState { | 25 struct BrowserTestMessagePumpAndroid::RunState { |
14 RunState(base::MessagePump::Delegate* delegate, int run_depth) | 26 RunState(base::MessagePump::Delegate* delegate, int run_depth) |
15 : delegate(delegate), | 27 : delegate(delegate), |
16 run_depth(run_depth), | 28 run_depth(run_depth), |
17 should_quit(false), | 29 should_quit(false), |
18 waitable_event(false, false) { | 30 waitable_event(false, false) { |
19 } | 31 } |
(...skipping 19 matching lines...) Expand all Loading... |
39 | 51 |
40 BrowserTestMessagePumpAndroid::~BrowserTestMessagePumpAndroid() { | 52 BrowserTestMessagePumpAndroid::~BrowserTestMessagePumpAndroid() { |
41 } | 53 } |
42 | 54 |
43 void BrowserTestMessagePumpAndroid::Run(Delegate* delegate) { | 55 void BrowserTestMessagePumpAndroid::Run(Delegate* delegate) { |
44 RunState state(delegate, state_ ? state_->run_depth + 1 : 1); | 56 RunState state(delegate, state_ ? state_->run_depth + 1 : 1); |
45 RunState* previous_state = state_; | 57 RunState* previous_state = state_; |
46 state_ = &state; | 58 state_ = &state; |
47 DCHECK(state_->run_depth <= 1) << "Only one level nested loops supported"; | 59 DCHECK(state_->run_depth <= 1) << "Only one level nested loops supported"; |
48 | 60 |
| 61 JNIEnv* env = base::android::AttachCurrentThread(); |
| 62 DCHECK(env); |
| 63 |
| 64 // Need to cap the wait time to allow task processing on the java |
| 65 // side. Otherwise, a long wait time on the native will starve java |
| 66 // tasks. |
| 67 base::TimeDelta max_delay = base::TimeDelta::FromMilliseconds(100); |
| 68 |
49 for (;;) { | 69 for (;;) { |
50 if (state_->should_quit) | 70 if (state_->should_quit) |
51 break; | 71 break; |
52 | 72 |
53 bool did_work = state_->delegate->DoWork(); | 73 bool did_work = state_->delegate->DoWork(); |
54 if (state_->should_quit) | 74 if (state_->should_quit) |
55 break; | 75 break; |
56 | 76 |
57 did_work |= state_->delegate->DoDelayedWork(&state_->delayed_work_time); | 77 did_work |= state_->delegate->DoDelayedWork(&state_->delayed_work_time); |
58 if (state_->should_quit) | 78 if (state_->should_quit) |
59 break; | 79 break; |
60 | 80 |
61 if (did_work) { | 81 if (did_work) { |
62 continue; | 82 continue; |
63 } | 83 } |
64 | 84 |
65 did_work = state_->delegate->DoIdleWork(); | 85 did_work = state_->delegate->DoIdleWork(); |
66 if (state_->should_quit) | 86 if (state_->should_quit) |
67 break; | 87 break; |
68 | 88 |
69 if (did_work) | 89 if (did_work) |
70 continue; | 90 continue; |
71 | 91 |
| 92 // No native tasks to process right now. Process tasks from the Java |
| 93 // System message handler. This will return when the java message queue |
| 94 // is idle. |
| 95 bool ret = Java_BrowserTestSystemMessageHandler_runNestedLoopTillIdle(env, |
| 96 g_message_handler_obj.Get().obj()); |
| 97 CHECK(ret) << "Error running java message loop, tests will likely fail."; |
| 98 |
72 if (state_->delayed_work_time.is_null()) { | 99 if (state_->delayed_work_time.is_null()) { |
73 state_->waitable_event.Wait(); | 100 state_->waitable_event.TimedWait(max_delay); |
74 } else { | 101 } else { |
75 base::TimeDelta delay = | 102 base::TimeDelta delay = |
76 state_->delayed_work_time - base::TimeTicks::Now(); | 103 state_->delayed_work_time - base::TimeTicks::Now(); |
| 104 if (delay > max_delay) |
| 105 delay = max_delay; |
77 if (delay > base::TimeDelta()) { | 106 if (delay > base::TimeDelta()) { |
78 state_->waitable_event.TimedWait(delay); | 107 state_->waitable_event.TimedWait(delay); |
79 } else { | 108 } else { |
80 // It looks like delayed_work_time indicates a time in the past, so we | 109 // It looks like delayed_work_time indicates a time in the past, so we |
81 // need to call DoDelayedWork now. | 110 // need to call DoDelayedWork now. |
82 state_->delayed_work_time = base::TimeTicks(); | 111 state_->delayed_work_time = base::TimeTicks(); |
83 } | 112 } |
84 } | 113 } |
85 } | 114 } |
86 | 115 |
87 state_ = previous_state; | 116 state_ = previous_state; |
88 } | 117 } |
89 | 118 |
| 119 void BrowserTestMessagePumpAndroid::Start( |
| 120 base::MessagePump::Delegate* delegate) { |
| 121 JNIEnv* env = base::android::AttachCurrentThread(); |
| 122 DCHECK(env); |
| 123 g_message_handler_obj.Get().Reset( |
| 124 Java_BrowserTestSystemMessageHandler_create(env)); |
| 125 |
| 126 base::MessagePumpForUI::Start(delegate); |
| 127 } |
| 128 |
90 void BrowserTestMessagePumpAndroid::Quit() { | 129 void BrowserTestMessagePumpAndroid::Quit() { |
91 if (state_) { | 130 if (state_) { |
92 state_->should_quit = true; | 131 state_->should_quit = true; |
93 state_->waitable_event.Signal(); | 132 state_->waitable_event.Signal(); |
94 return; | 133 return; |
95 } | 134 } |
96 | |
97 base::MessagePumpForUI::Quit(); | 135 base::MessagePumpForUI::Quit(); |
98 } | 136 } |
99 | 137 |
100 void BrowserTestMessagePumpAndroid::ScheduleWork() { | 138 void BrowserTestMessagePumpAndroid::ScheduleWork() { |
101 if (state_) { | 139 if (state_) { |
102 state_->waitable_event.Signal(); | 140 state_->waitable_event.Signal(); |
103 return; | 141 return; |
104 } | 142 } |
105 | 143 |
106 base::MessagePumpForUI::ScheduleWork(); | 144 base::MessagePumpForUI::ScheduleWork(); |
107 } | 145 } |
108 | 146 |
109 void BrowserTestMessagePumpAndroid::ScheduleDelayedWork( | 147 void BrowserTestMessagePumpAndroid::ScheduleDelayedWork( |
110 const base::TimeTicks& delayed_work_time) { | 148 const base::TimeTicks& delayed_work_time) { |
111 if (state_) { | 149 if (state_) { |
112 // We know that we can't be blocked on Wait right now since this method can | 150 // We know that we can't be blocked on Wait right now since this method can |
113 // only be called on the same thread as Run, so we only need to update our | 151 // only be called on the same thread as Run, so we only need to update our |
114 // record of how long to sleep when we do sleep. | 152 // record of how long to sleep when we do sleep. |
115 state_->delayed_work_time = delayed_work_time; | 153 state_->delayed_work_time = delayed_work_time; |
116 return; | 154 return; |
117 } | 155 } |
118 | 156 |
119 base::MessagePumpForUI::ScheduleDelayedWork(delayed_work_time); | 157 base::MessagePumpForUI::ScheduleDelayedWork(delayed_work_time); |
120 } | 158 } |
121 | 159 |
122 } // namespace base | 160 // static |
| 161 bool BrowserTestMessagePumpAndroid::RegisterJni(JNIEnv* env) { |
| 162 return RegisterNativesImpl(env); |
| 163 } |
| 164 |
| 165 } // namespace content |
OLD | NEW |