summaryrefslogtreecommitdiffstats
path: root/android_webview
diff options
context:
space:
mode:
authortimvolodine <timvolodine@chromium.org>2015-12-02 07:05:21 -0800
committerCommit bot <commit-bot@chromium.org>2015-12-02 15:06:31 +0000
commit08ac6e256a84463af2b2c55bdb7e91d55d6cea57 (patch)
tree04d2080844e8a1e005e428d1b6f6ef4c01b0ad40 /android_webview
parent186cb343ee13c12b68110bb687f1087347abadbb (diff)
downloadchromium_src-08ac6e256a84463af2b2c55bdb7e91d55d6cea57.zip
chromium_src-08ac6e256a84463af2b2c55bdb7e91d55d6cea57.tar.gz
chromium_src-08ac6e256a84463af2b2c55bdb7e91d55d6cea57.tar.bz2
[Android WebView] Implement AwContentsLifecycleNotifier.
This patch provides a way to observe webview lifecycle on the java side. By implementing AwContentsLifecycleNotifier.Observer and registering with the notifier, clients will get notified when there are alive instances of webviews (i.e. aw_contents) or when all webview instances have been destroyed. This is useful for APIs which can be disabled when there are no living webviews, e.g. Network Information API. BUG=520088 Review URL: https://codereview.chromium.org/1419083010 Cr-Commit-Position: refs/heads/master@{#362706}
Diffstat (limited to 'android_webview')
-rw-r--r--android_webview/java/src/org/chromium/android_webview/AwContentsLifecycleNotifier.java74
-rw-r--r--android_webview/javatests/src/org/chromium/android_webview/test/AwContentsLifecycleNotifierTest.java57
-rw-r--r--android_webview/native/BUILD.gn3
-rw-r--r--android_webview/native/android_webview_jni_registrar.cc2
-rw-r--r--android_webview/native/aw_contents.cc5
-rw-r--r--android_webview/native/aw_contents_lifecycle_notifier.cc27
-rw-r--r--android_webview/native/aw_contents_lifecycle_notifier.h26
-rw-r--r--android_webview/native/webview_native.gyp3
8 files changed, 197 insertions, 0 deletions
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsLifecycleNotifier.java b/android_webview/java/src/org/chromium/android_webview/AwContentsLifecycleNotifier.java
new file mode 100644
index 0000000..6701c95
--- /dev/null
+++ b/android_webview/java/src/org/chromium/android_webview/AwContentsLifecycleNotifier.java
@@ -0,0 +1,74 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.android_webview;
+
+import org.chromium.base.ObserverList;
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+
+/**
+ * This class is intended to notify observers of the existence native instances of
+ * aw_contents. It receives a callback when native aw_contents are created or
+ * destroyed. Observers are notified when the first instance is created or the
+ * last instance is destroyed.
+ */
+@JNINamespace("android_webview")
+public class AwContentsLifecycleNotifier {
+
+ /**
+ * Observer interface to be implemented by deriving webview lifecycle observers.
+ */
+ public static interface Observer {
+ public void onFirstWebViewCreated();
+ public void onLastWebViewDestroyed();
+ }
+
+ private static final ObserverList<Observer> sLifecycleObservers =
+ new ObserverList<Observer>();
+ private static int sNumWebViews = 0;
+
+ private AwContentsLifecycleNotifier() {}
+
+ public static void addObserver(Observer observer) {
+ sLifecycleObservers.addObserver(observer);
+ }
+
+ public static void removeObserver(Observer observer) {
+ sLifecycleObservers.removeObserver(observer);
+ }
+
+ public static boolean hasWebViewInstances() {
+ return sNumWebViews > 0;
+ }
+
+ // Called on UI thread.
+ @CalledByNative
+ private static void onWebViewCreated() {
+ ThreadUtils.assertOnUiThread();
+ assert sNumWebViews >= 0;
+ sNumWebViews++;
+ if (sNumWebViews == 1) {
+ // first webview created, notify observers.
+ for (Observer observer : sLifecycleObservers) {
+ observer.onFirstWebViewCreated();
+ }
+ }
+ }
+
+ // Called on UI thread.
+ @CalledByNative
+ private static void onWebViewDestroyed() {
+ ThreadUtils.assertOnUiThread();
+ assert sNumWebViews > 0;
+ sNumWebViews--;
+ if (sNumWebViews == 0) {
+ // last webview destroyed, notify observers.
+ for (Observer observer : sLifecycleObservers) {
+ observer.onLastWebViewDestroyed();
+ }
+ }
+ }
+}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsLifecycleNotifierTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsLifecycleNotifierTest.java
new file mode 100644
index 0000000..2c7d408
--- /dev/null
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsLifecycleNotifierTest.java
@@ -0,0 +1,57 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.android_webview.test;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.chromium.android_webview.AwContentsLifecycleNotifier;
+import org.chromium.base.test.util.Feature;
+import org.chromium.content.browser.test.util.CallbackHelper;
+
+/**
+ * AwContentsLifecycleNotifier tests.
+ */
+public class AwContentsLifecycleNotifierTest extends AwTestBase {
+
+ private TestAwContentsClient mContentsClient = new TestAwContentsClient();
+
+ private static class LifecycleObserver implements AwContentsLifecycleNotifier.Observer {
+ public CallbackHelper mFirstWebViewCreatedCallback = new CallbackHelper();
+ public CallbackHelper mLastWebViewDestroyedCallback = new CallbackHelper();
+
+ @Override
+ public void onFirstWebViewCreated() {
+ mFirstWebViewCreatedCallback.notifyCalled();
+ }
+
+ @Override
+ public void onLastWebViewDestroyed() {
+ mLastWebViewDestroyedCallback.notifyCalled();
+ }
+ }
+
+ @SmallTest
+ @Feature({"AndroidWebView"})
+ public void testNotifierCreate() throws Throwable {
+ LifecycleObserver observer = new LifecycleObserver();
+ AwContentsLifecycleNotifier.addObserver(observer);
+ assertFalse(AwContentsLifecycleNotifier.hasWebViewInstances());
+
+ AwTestContainerView awTestContainerView =
+ createAwTestContainerViewOnMainSync(mContentsClient);
+ observer.mFirstWebViewCreatedCallback.waitForCallback(0, 1);
+ assertTrue(AwContentsLifecycleNotifier.hasWebViewInstances());
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ getActivity().removeAllViews();
+ }
+ });
+ destroyAwContentsOnMainSync(awTestContainerView.getAwContents());
+ observer.mLastWebViewDestroyedCallback.waitForCallback(0, 1);
+ assertFalse(AwContentsLifecycleNotifier.hasWebViewInstances());
+ }
+}
diff --git a/android_webview/native/BUILD.gn b/android_webview/native/BUILD.gn
index 320cbb3..cec2c0e 100644
--- a/android_webview/native/BUILD.gn
+++ b/android_webview/native/BUILD.gn
@@ -47,6 +47,8 @@ source_set("native") {
"aw_contents_client_bridge.h",
"aw_contents_io_thread_client_impl.cc",
"aw_contents_io_thread_client_impl.h",
+ "aw_contents_lifecycle_notifier.cc",
+ "aw_contents_lifecycle_notifier.h",
"aw_contents_statics.cc",
"aw_contents_statics.h",
"aw_debug.cc",
@@ -118,6 +120,7 @@ generate_jni("native_jni") {
"../java/src/org/chromium/android_webview/AwContentsBackgroundThreadClient.java",
"../java/src/org/chromium/android_webview/AwContentsClientBridge.java",
"../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java",
+ "../java/src/org/chromium/android_webview/AwContentsLifecycleNotifier.java",
"../java/src/org/chromium/android_webview/AwContentsStatics.java",
"../java/src/org/chromium/android_webview/AwCookieManager.java",
"../java/src/org/chromium/android_webview/AwDebug.java",
diff --git a/android_webview/native/android_webview_jni_registrar.cc b/android_webview/native/android_webview_jni_registrar.cc
index 275e29b..a585d7e 100644
--- a/android_webview/native/android_webview_jni_registrar.cc
+++ b/android_webview/native/android_webview_jni_registrar.cc
@@ -10,6 +10,7 @@
#include "android_webview/native/aw_contents_background_thread_client.h"
#include "android_webview/native/aw_contents_client_bridge.h"
#include "android_webview/native/aw_contents_io_thread_client_impl.h"
+#include "android_webview/native/aw_contents_lifecycle_notifier.h"
#include "android_webview/native/aw_contents_statics.h"
#include "android_webview/native/aw_debug.h"
#include "android_webview/native/aw_dev_tools_server.h"
@@ -59,6 +60,7 @@ static base::android::RegistrationMethod kWebViewRegisteredMethods[] = {
{ "InputStream", RegisterInputStream },
{ "JavaBrowserViewRendererHelper", RegisterJavaBrowserViewRendererHelper },
{ "AwMessagePortService", RegisterAwMessagePortService },
+ { "AwContentsLifecycleNotifier", RegisterAwContentsLifecycleNotifier },
};
bool RegisterJni(JNIEnv* env) {
diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc
index 4a829fa..8ec6260 100644
--- a/android_webview/native/aw_contents.cc
+++ b/android_webview/native/aw_contents.cc
@@ -22,6 +22,7 @@
#include "android_webview/native/aw_browser_dependency_factory.h"
#include "android_webview/native/aw_contents_client_bridge.h"
#include "android_webview/native/aw_contents_io_thread_client_impl.h"
+#include "android_webview/native/aw_contents_lifecycle_notifier.h"
#include "android_webview/native/aw_message_port_service_impl.h"
#include "android_webview/native/aw_pdf_exporter.h"
#include "android_webview/native/aw_picture.h"
@@ -209,6 +210,7 @@ AwContents::AwContents(scoped_ptr<WebContents> web_contents)
InitAutofillIfNecessary(autofill_manager_delegate->GetSaveFormData());
content::SynchronousCompositor::SetClientForWebContents(
web_contents_.get(), &browser_view_renderer_);
+ AwContentsLifecycleNotifier::OnWebViewCreated();
}
void AwContents::SetJavaPeers(JNIEnv* env,
@@ -293,9 +295,12 @@ AwContents::~AwContents() {
// Chromium, because the app process may continue to run for a long time
// without ever using another WebView.
if (instance_count == 0) {
+ // TODO(timvolodine): consider moving NotifyMemoryPressure to
+ // AwContentsLifecycleNotifier (crbug.com/522988).
base::MemoryPressureListener::NotifyMemoryPressure(
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
}
+ AwContentsLifecycleNotifier::OnWebViewDestroyed();
}
base::android::ScopedJavaLocalRef<jobject>
diff --git a/android_webview/native/aw_contents_lifecycle_notifier.cc b/android_webview/native/aw_contents_lifecycle_notifier.cc
new file mode 100644
index 0000000..0644ed7
--- /dev/null
+++ b/android_webview/native/aw_contents_lifecycle_notifier.cc
@@ -0,0 +1,27 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "android_webview/native/aw_contents_lifecycle_notifier.h"
+
+#include "jni/AwContentsLifecycleNotifier_jni.h"
+
+using base::android::AttachCurrentThread;
+
+namespace android_webview {
+
+bool RegisterAwContentsLifecycleNotifier(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+// static
+void AwContentsLifecycleNotifier::OnWebViewCreated() {
+ Java_AwContentsLifecycleNotifier_onWebViewCreated(AttachCurrentThread());
+}
+
+// static
+void AwContentsLifecycleNotifier::OnWebViewDestroyed() {
+ Java_AwContentsLifecycleNotifier_onWebViewDestroyed(AttachCurrentThread());
+}
+
+} // namespace android_webview
diff --git a/android_webview/native/aw_contents_lifecycle_notifier.h b/android_webview/native/aw_contents_lifecycle_notifier.h
new file mode 100644
index 0000000..7965f11
--- /dev/null
+++ b/android_webview/native/aw_contents_lifecycle_notifier.h
@@ -0,0 +1,26 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_WEBVIEW_NATIVE_AW_CONTENTS_LIFECYCLE_OBSERVER_H_
+#define ANDROID_WEBVIEW_NATIVE_AW_CONTENTS_LIFECYCLE_OBSERVER_H_
+
+#include "base/android/jni_android.h"
+#include "base/macros.h"
+
+namespace android_webview {
+
+class AwContentsLifecycleNotifier {
+ public:
+ static void OnWebViewCreated();
+ static void OnWebViewDestroyed();
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(AwContentsLifecycleNotifier);
+};
+
+bool RegisterAwContentsLifecycleNotifier(JNIEnv* env);
+
+} // namespace android_webview
+
+#endif
diff --git a/android_webview/native/webview_native.gyp b/android_webview/native/webview_native.gyp
index 020f0a8..97d941e 100644
--- a/android_webview/native/webview_native.gyp
+++ b/android_webview/native/webview_native.gyp
@@ -50,6 +50,8 @@
'aw_contents_client_bridge.h',
'aw_contents_io_thread_client_impl.cc',
'aw_contents_io_thread_client_impl.h',
+ 'aw_contents_lifecycle_notifier.cc',
+ 'aw_contents_lifecycle_notifier.h',
'aw_contents_statics.cc',
'aw_contents_statics.h',
'aw_debug.cc',
@@ -135,6 +137,7 @@
'../java/src/org/chromium/android_webview/AwContentsBackgroundThreadClient.java',
'../java/src/org/chromium/android_webview/AwContentsClientBridge.java',
'../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java',
+ '../java/src/org/chromium/android_webview/AwContentsLifecycleNotifier.java',
'../java/src/org/chromium/android_webview/AwContentsStatics.java',
'../java/src/org/chromium/android_webview/AwCookieManager.java',
'../java/src/org/chromium/android_webview/AwDebug.java',