nested_message_pump_android.cc revision 58537e28ecd584eab876aee8be7156509866d23a
1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/test/nested_message_pump_android.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/android/jni_android.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/android/scoped_java_ref.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/lazy_instance.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/waitable_event.h" 1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/threading/thread_restrictions.h" 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "jni/NestedSystemMessageHandler_jni.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject> > 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_message_handler_obj = LAZY_INSTANCE_INITIALIZER; 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content { 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstruct NestedMessagePumpAndroid::RunState { 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunState(base::MessagePump::Delegate* delegate, int run_depth) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : delegate(delegate), 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) run_depth(run_depth), 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) should_quit(false), 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) waitable_event(false, false) { 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::MessagePump::Delegate* delegate; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Used to count how many Run() invocations are on the stack. 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int run_depth; 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Used to flag that the current Run() invocation should return ASAP. 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool should_quit; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Used to sleep until there is more work to do. 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEvent waitable_event; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The time at which we should call DoDelayedWork. 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks delayed_work_time; 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochNestedMessagePumpAndroid::NestedMessagePumpAndroid() 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : state_(NULL) { 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochNestedMessagePumpAndroid::~NestedMessagePumpAndroid() { 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid NestedMessagePumpAndroid::Run(Delegate* delegate) { 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunState state(delegate, state_ ? state_->run_depth + 1 : 1); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunState* previous_state = state_; 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_ = &state; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) JNIEnv* env = base::android::AttachCurrentThread(); 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(env); 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Need to cap the wait time to allow task processing on the java 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // side. Otherwise, a long wait time on the native will starve java 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // tasks. 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta max_delay = base::TimeDelta::FromMilliseconds(100); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (;;) { 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (state_->should_quit) 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool did_work = state_->delegate->DoWork(); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (state_->should_quit) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) did_work |= state_->delegate->DoDelayedWork(&state_->delayed_work_time); 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (state_->should_quit) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (did_work) { 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) did_work = state_->delegate->DoIdleWork(); 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (state_->should_quit) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (did_work) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // No native tasks to process right now. Process tasks from the Java 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // System message handler. This will return when the java message queue 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is idle. 95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool ret = Java_NestedSystemMessageHandler_runNestedLoopTillIdle(env, 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_message_handler_obj.Get().obj()); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(ret) << "Error running java message loop, tests will likely fail."; 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::ThreadRestrictions::ScopedAllowWait allow_wait; 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (state_->delayed_work_time.is_null()) { 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_->waitable_event.TimedWait(max_delay); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta delay = 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_->delayed_work_time - base::TimeTicks::Now(); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (delay > max_delay) 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delay = max_delay; 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (delay > base::TimeDelta()) { 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_->waitable_event.TimedWait(delay); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // It looks like delayed_work_time indicates a time in the past, so we 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // need to call DoDelayedWork now. 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_->delayed_work_time = base::TimeTicks(); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_ = previous_state; 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid NestedMessagePumpAndroid::Start( 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::MessagePump::Delegate* delegate) { 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) JNIEnv* env = base::android::AttachCurrentThread(); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(env); 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_message_handler_obj.Get().Reset( 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Java_NestedSystemMessageHandler_create(env)); 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::MessagePumpForUI::Start(delegate); 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid NestedMessagePumpAndroid::Quit() { 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (state_) { 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_->should_quit = true; 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_->waitable_event.Signal(); 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::MessagePumpForUI::Quit(); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid NestedMessagePumpAndroid::ScheduleWork() { 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (state_) { 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_->waitable_event.Signal(); 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::MessagePumpForUI::ScheduleWork(); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid NestedMessagePumpAndroid::ScheduleDelayedWork( 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::TimeTicks& delayed_work_time) { 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (state_) { 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We know that we can't be blocked on Wait right now since this method can 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // only be called on the same thread as Run, so we only need to update our 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // record of how long to sleep when we do sleep. 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_->delayed_work_time = delayed_work_time; 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::MessagePumpForUI::ScheduleDelayedWork(delayed_work_time); 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool NestedMessagePumpAndroid::RegisterJni(JNIEnv* env) { 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return RegisterNativesImpl(env); 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace content 167