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 <jni.h> 6#include <vector> 7 8#include "base/android/jni_android.h" 9#include "base/android/jni_string.h" 10#include "base/android/scoped_java_ref.h" 11#include "base/basictypes.h" 12#include "base/lazy_instance.h" 13#include "base/logging.h" 14#include "content/browser/android/content_view_statics.h" 15#include "content/common/android/address_parser.h" 16#include "content/common/view_messages.h" 17#include "content/public/browser/render_process_host.h" 18#include "content/public/browser/render_process_host_observer.h" 19#include "jni/ContentViewStatics_jni.h" 20 21using base::android::ConvertJavaStringToUTF16; 22using base::android::ConvertUTF16ToJavaString; 23 24namespace { 25 26// TODO(pliard): http://crbug.com/235909. Move WebKit shared timer toggling 27// functionality out of ContentViewStatistics and not be build on top of 28// blink::Platform::SuspendSharedTimer. 29// TODO(pliard): http://crbug.com/235912. Add unit tests for WebKit shared timer 30// toggling. 31 32// This tracks the renderer processes that received a suspend request. It's 33// important on resume to only resume the renderer processes that were actually 34// suspended as opposed to all the current renderer processes because the 35// suspend calls are refcounted within WebKitPlatformSupport and it expects a 36// perfectly matched number of resume calls. 37// Note that this class is only accessed from the UI thread. 38class SuspendedProcessWatcher : public content::RenderProcessHostObserver { 39 public: 40 41 // If the process crashes, stop watching the corresponding RenderProcessHost 42 // and ensure it doesn't get over-resumed. 43 virtual void RenderProcessExited(content::RenderProcessHost* host, 44 base::ProcessHandle handle, 45 base::TerminationStatus status, 46 int exit_code) OVERRIDE { 47 StopWatching(host); 48 } 49 50 virtual void RenderProcessHostDestroyed( 51 content::RenderProcessHost* host) OVERRIDE { 52 StopWatching(host); 53 } 54 55 // Suspends timers in all current render processes. 56 void SuspendWebKitSharedTimers() { 57 DCHECK(suspended_processes_.empty()); 58 59 for (content::RenderProcessHost::iterator i( 60 content::RenderProcessHost::AllHostsIterator()); 61 !i.IsAtEnd(); i.Advance()) { 62 content::RenderProcessHost* host = i.GetCurrentValue(); 63 host->AddObserver(this); 64 host->Send(new ViewMsg_SetWebKitSharedTimersSuspended(true)); 65 suspended_processes_.push_back(host->GetID()); 66 } 67 } 68 69 // Resumes timers in processes that were previously stopped. 70 void ResumeWebkitSharedTimers() { 71 for (std::vector<int>::const_iterator it = suspended_processes_.begin(); 72 it != suspended_processes_.end(); ++it) { 73 content::RenderProcessHost* host = 74 content::RenderProcessHost::FromID(*it); 75 DCHECK(host); 76 host->RemoveObserver(this); 77 host->Send(new ViewMsg_SetWebKitSharedTimersSuspended(false)); 78 } 79 suspended_processes_.clear(); 80 } 81 82 private: 83 void StopWatching(content::RenderProcessHost* host) { 84 std::vector<int>::iterator pos = std::find(suspended_processes_.begin(), 85 suspended_processes_.end(), 86 host->GetID()); 87 DCHECK_NE(pos, suspended_processes_.end()); 88 host->RemoveObserver(this); 89 suspended_processes_.erase(pos); 90 } 91 92 std::vector<int /* RenderProcessHost id */> suspended_processes_; 93}; 94 95base::LazyInstance<SuspendedProcessWatcher> g_suspended_processes_watcher = 96 LAZY_INSTANCE_INITIALIZER; 97 98} // namespace 99 100// Returns the first substring consisting of the address of a physical location. 101static jstring FindAddress(JNIEnv* env, jclass clazz, jstring addr) { 102 base::string16 content_16 = ConvertJavaStringToUTF16(env, addr); 103 base::string16 result_16; 104 if (content::address_parser::FindAddress(content_16, &result_16)) 105 return ConvertUTF16ToJavaString(env, result_16).Release(); 106 return NULL; 107} 108 109static void SetWebKitSharedTimersSuspended(JNIEnv* env, 110 jclass obj, 111 jboolean suspend) { 112 if (suspend) { 113 g_suspended_processes_watcher.Pointer()->SuspendWebKitSharedTimers(); 114 } else { 115 g_suspended_processes_watcher.Pointer()->ResumeWebkitSharedTimers(); 116 } 117} 118 119namespace content { 120 121bool RegisterWebViewStatics(JNIEnv* env) { 122 return RegisterNativesImpl(env); 123} 124 125} // namespace content 126