• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 using base::android::ConvertJavaStringToUTF16;
22 using base::android::ConvertUTF16ToJavaString;
23 
24 namespace {
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.
38 class 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.
RenderProcessExited(content::RenderProcessHost * host,base::ProcessHandle handle,base::TerminationStatus status,int exit_code)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 
RenderProcessHostDestroyed(content::RenderProcessHost * host)50   virtual void RenderProcessHostDestroyed(
51       content::RenderProcessHost* host) OVERRIDE {
52     StopWatching(host);
53   }
54 
55   // Suspends timers in all current render processes.
SuspendWebKitSharedTimers()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.
ResumeWebkitSharedTimers()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:
StopWatching(content::RenderProcessHost * host)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 
95 base::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.
FindAddress(JNIEnv * env,jclass clazz,jstring addr)101 static 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 
SetWebKitSharedTimersSuspended(JNIEnv * env,jclass obj,jboolean suspend)109 static 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 
119 namespace content {
120 
RegisterWebViewStatics(JNIEnv * env)121 bool RegisterWebViewStatics(JNIEnv* env) {
122   return RegisterNativesImpl(env);
123 }
124 
125 }  // namespace content
126