Home | History | Annotate | Download | only in android
      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.
     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 
     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.
    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 
    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 
    121 bool RegisterWebViewStatics(JNIEnv* env) {
    122   return RegisterNativesImpl(env);
    123 }
    124 
    125 }  // namespace content
    126