Merge "Revert "[Android WebView] Make web contents debugging controllable"" into klp-dev
diff --git a/android_webview/browser/in_process_view_renderer.cc b/android_webview/browser/in_process_view_renderer.cc
index 7c84cc9..68beacf 100644
--- a/android_webview/browser/in_process_view_renderer.cc
+++ b/android_webview/browser/in_process_view_renderer.cc
@@ -377,12 +377,10 @@
gpu::InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread();
ScopedAllowGL allow_gl;
- if (attached_to_window_ && compositor_ && !hardware_initialized_) {
- if (InitializeHwDraw()) {
- last_egl_context_ = current_context;
- } else {
- return;
- }
+ if (!attached_to_window_) {
+ TRACE_EVENT_INSTANT0(
+ "android_webview", "EarlyOut_NotAttached", TRACE_EVENT_SCOPE_THREAD);
+ return;
}
if (draw_info->mode == AwDrawGLInfo::kModeProcess) {
@@ -391,6 +389,17 @@
return;
}
+ if (compositor_ && !hardware_initialized_) {
+ if (InitializeHwDraw()) {
+ last_egl_context_ = current_context;
+ } else {
+ TRACE_EVENT_INSTANT0(
+ "android_webview", "EarlyOut_HwInitFail", TRACE_EVENT_SCOPE_THREAD);
+ LOG(ERROR) << "WebView hardware initialization failed";
+ return;
+ }
+ }
+
UpdateCachedGlobalVisibleRect();
if (cached_global_visible_rect_.IsEmpty()) {
TRACE_EVENT_INSTANT0("android_webview",
diff --git a/android_webview/browser/renderer_host/aw_render_view_host_ext.cc b/android_webview/browser/renderer_host/aw_render_view_host_ext.cc
index dff3b81..5ea13e2 100644
--- a/android_webview/browser/renderer_host/aw_render_view_host_ext.cc
+++ b/android_webview/browser/renderer_host/aw_render_view_host_ext.cc
@@ -141,6 +141,8 @@
OnPageScaleFactorChanged)
IPC_MESSAGE_HANDLER(AwViewHostMsg_OnContentsSizeChanged,
OnContentsSizeChanged)
+ IPC_MESSAGE_HANDLER(AwViewHostMsg_ShouldOverrideUrlLoading,
+ OnShouldOverrideUrlLoading)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -176,4 +178,10 @@
client_->OnWebLayoutContentsSizeChanged(contents_size);
}
+void AwRenderViewHostExt::OnShouldOverrideUrlLoading(const base::string16& url,
+ bool* ignore_navigation) {
+
+ *ignore_navigation = client_->OnShouldOverrideUrlLoading(url);
+}
+
} // namespace android_webview
diff --git a/android_webview/browser/renderer_host/aw_render_view_host_ext.h b/android_webview/browser/renderer_host/aw_render_view_host_ext.h
index d4e0256..1917d18 100644
--- a/android_webview/browser/renderer_host/aw_render_view_host_ext.h
+++ b/android_webview/browser/renderer_host/aw_render_view_host_ext.h
@@ -28,6 +28,8 @@
virtual void OnWebLayoutPageScaleFactorChanged(float page_scale_factor) = 0;
virtual void OnWebLayoutContentsSizeChanged(
const gfx::Size& contents_size) = 0;
+ // Called when there is a top level navigation.
+ virtual bool OnShouldOverrideUrlLoading(const base::string16& url) = 0;
protected:
virtual ~AwRenderViewHostExtClient() {}
@@ -92,6 +94,8 @@
void OnUpdateHitTestData(const AwHitTestData& hit_test_data);
void OnPageScaleFactorChanged(float page_scale_factor);
void OnContentsSizeChanged(const gfx::Size& contents_size);
+ void OnShouldOverrideUrlLoading(const base::string16& url,
+ bool* ignore_navigation);
bool IsRenderViewReady() const;
diff --git a/android_webview/common/render_view_messages.h b/android_webview/common/render_view_messages.h
index 80e2471..2c4ea67 100644
--- a/android_webview/common/render_view_messages.h
+++ b/android_webview/common/render_view_messages.h
@@ -99,3 +99,10 @@
// Sent whenever the contents size (as seen by RenderView) is changed.
IPC_MESSAGE_ROUTED1(AwViewHostMsg_OnContentsSizeChanged,
gfx::Size /* contents_size */)
+
+// Sent when there is a top level navigation. Returning true means
+// the application will handle this request and so will cancel the
+// navigation within Blink.
+IPC_SYNC_MESSAGE_ROUTED1_1(AwViewHostMsg_ShouldOverrideUrlLoading,
+ string16 /* in - url */,
+ bool /* out - result */)
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index 121badd..c4c798a 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -48,7 +48,6 @@
import org.chromium.content.browser.NavigationHistory;
import org.chromium.content.browser.PageTransitionTypes;
import org.chromium.content.common.CleanupReference;
-import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
import org.chromium.components.navigation_interception.NavigationParams;
import org.chromium.net.GURLUtils;
import org.chromium.ui.gfx.DeviceDisplayInfo;
@@ -149,7 +148,6 @@
private final AwContentsClientBridge mContentsClientBridge;
private final AwWebContentsDelegate mWebContentsDelegate;
private final AwContentsIoThreadClient mIoThreadClient;
- private final InterceptNavigationDelegateImpl mInterceptNavigationDelegate;
private final InternalAccessDelegate mInternalAccessAdapter;
private final AwLayoutSizer mLayoutSizer;
private final AwZoomControls mZoomControls;
@@ -272,67 +270,6 @@
}
//--------------------------------------------------------------------------------------------
- private class InterceptNavigationDelegateImpl implements InterceptNavigationDelegate {
- private String mLastLoadUrlAddress;
-
- public void onUrlLoadRequested(String url) {
- mLastLoadUrlAddress = url;
- }
-
- @Override
- public boolean shouldIgnoreNavigation(NavigationParams navigationParams) {
- final String url = navigationParams.url;
- final int transitionType = navigationParams.pageTransitionType;
- final boolean isLoadUrl =
- (transitionType & PageTransitionTypes.PAGE_TRANSITION_FROM_API) != 0;
- final boolean isBackForward =
- (transitionType & PageTransitionTypes.PAGE_TRANSITION_FORWARD_BACK) != 0;
- final boolean isReload =
- (transitionType & PageTransitionTypes.PAGE_TRANSITION_CORE_MASK) ==
- PageTransitionTypes.PAGE_TRANSITION_RELOAD;
- final boolean isRedirect = navigationParams.isRedirect;
-
- boolean ignoreNavigation = false;
-
- // Any navigation from loadUrl, goBack/Forward, or reload, are considered application
- // initiated and hence will not yield a shouldOverrideUrlLoading() callback.
- // TODO(joth): Using PageTransitionTypes should be sufficient to determine all app
- // initiated navigations, and so mLastLoadUrlAddress should be removed.
- if ((isLoadUrl && !isRedirect) || isBackForward || isReload ||
- mLastLoadUrlAddress != null && mLastLoadUrlAddress.equals(url)) {
- // Support the case where the user clicks on a link that takes them back to the
- // same page.
- mLastLoadUrlAddress = null;
-
- // If the embedder requested the load of a certain URL via the loadUrl API, then we
- // do not offer it to AwContentsClient.shouldOverrideUrlLoading.
- // The embedder is also not allowed to intercept POST requests because of
- // crbug.com/155250.
- } else if (!navigationParams.isPost) {
- ignoreNavigation = mContentsClient.shouldOverrideUrlLoading(url);
- }
-
- // The existing contract is that shouldOverrideUrlLoading callbacks are delivered before
- // onPageStarted callbacks; third party apps depend on this behavior.
- // Using a ResouceThrottle to implement the navigation interception feature results in
- // the WebContentsObserver.didStartLoading callback happening before the
- // ResourceThrottle has a chance to run.
- // To preserve the ordering the onPageStarted callback is synthesized from the
- // shouldOverrideUrlLoading, and only if the navigation was not ignored (this
- // balances out with the onPageFinished callback, which is suppressed in the
- // AwContentsClient if the navigation was ignored).
- if (!ignoreNavigation) {
- // The shouldOverrideUrlLoading call might have resulted in posting messages to the
- // UI thread. Using sendMessage here (instead of calling onPageStarted directly)
- // will allow those to run in order.
- mContentsClient.getCallbackHelper().postOnPageStarted(url);
- }
-
- return ignoreNavigation;
- }
- }
-
- //--------------------------------------------------------------------------------------------
private class AwLayoutSizerDelegate implements AwLayoutSizer.Delegate {
@Override
public void requestLayout() {
@@ -498,7 +435,6 @@
mContentsClientBridge = new AwContentsClientBridge(contentsClient);
mZoomControls = new AwZoomControls(this);
mIoThreadClient = new IoThreadClientImpl();
- mInterceptNavigationDelegate = new InterceptNavigationDelegateImpl();
boolean hasInternetPermission = containerView.getContext().checkPermission(
android.Manifest.permission.INTERNET,
@@ -558,7 +494,7 @@
new AwGestureStateListener(), mContentsClient.getContentViewClient(),
mZoomControls);
nativeSetJavaPeers(mNativeAwContents, this, mWebContentsDelegate, mContentsClientBridge,
- mIoThreadClient, mInterceptNavigationDelegate);
+ mIoThreadClient);
mContentsClient.installWebContentsObserver(mContentViewCore);
mContentViewCore.setUpdateFrameInfoListener(new AwContentUpdateFrameInfoListener());
mSettings.setWebContents(nativeWebContents);
@@ -867,8 +803,6 @@
mContentViewCore.loadUrl(params);
- suppressInterceptionForThisNavigation();
-
// The behavior of WebViewClassic uses the populateVisitedLinks callback in WebKit.
// Chromium does not use this use code path and the best emulation of this behavior to call
// request visited links once on the first URL load of the WebView.
@@ -878,14 +812,6 @@
}
}
- private void suppressInterceptionForThisNavigation() {
- if (mInterceptNavigationDelegate != null) {
- // getUrl returns a sanitized address in the same format that will be used for
- // callbacks, so it's safe to use string comparison as an equality check later on.
- mInterceptNavigationDelegate.onUrlLoadRequested(mContentViewCore.getUrl());
- }
- }
-
/**
* Get the URL of the current page.
*
@@ -1097,8 +1023,6 @@
*/
public void goBack() {
mContentViewCore.goBack();
-
- suppressInterceptionForThisNavigation();
}
/**
@@ -1113,8 +1037,6 @@
*/
public void goForward() {
mContentViewCore.goForward();
-
- suppressInterceptionForThisNavigation();
}
/**
@@ -1129,8 +1051,6 @@
*/
public void goBackOrForward(int steps) {
mContentViewCore.goToOffset(steps);
-
- suppressInterceptionForThisNavigation();
}
/**
@@ -1807,6 +1727,11 @@
}
@CalledByNative
+ private boolean onShouldOverrideUrlLoading(String url) {
+ return mContentsClient.shouldOverrideUrlLoading(url);
+ }
+
+ @CalledByNative
private void scrollContainerViewTo(int x, int y) {
mScrollOffsetManager.scrollContainerViewTo(x, y);
}
@@ -1894,8 +1819,7 @@
private native void nativeSetJavaPeers(int nativeAwContents, AwContents awContents,
AwWebContentsDelegate webViewWebContentsDelegate,
AwContentsClientBridge contentsClientBridge,
- AwContentsIoThreadClient ioThreadClient,
- InterceptNavigationDelegate navigationInterceptionDelegate);
+ AwContentsIoThreadClient ioThreadClient);
private native int nativeGetWebContents(int nativeAwContents);
private native void nativeDocumentHasImages(int nativeAwContents, Message message);
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
index 3f2245c..bd6dfd4 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
@@ -64,6 +64,11 @@
}
@Override
+ public void didStartLoading(String url) {
+ AwContentsClient.this.onPageStarted(url);
+ }
+
+ @Override
public void didStopLoading(String url) {
AwContentsClient.this.onPageFinished(url);
}
diff --git a/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java b/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java
index 20ac8b5..97efee1 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java
@@ -38,7 +38,7 @@
private double mDIPScale;
- // Was our heightSpec is AT_MOST the last time onMeasure was called?
+ // Was our height larger than the AT_MOST constraint the last time onMeasure was called?
private boolean mHeightMeasurementLimited;
// If mHeightMeasurementLimited is true then this contains the height limit.
private int mHeightMeasurementLimit;
@@ -152,12 +152,11 @@
// Always use the given size unless unspecified. This matches WebViewClassic behavior.
mWidthMeasurementIsFixed = (widthMode != MeasureSpec.UNSPECIFIED);
mHeightMeasurementIsFixed = (heightMode == MeasureSpec.EXACTLY);
- mHeightMeasurementLimited = (heightMode == MeasureSpec.AT_MOST);
+ mHeightMeasurementLimited =
+ (heightMode == MeasureSpec.AT_MOST) && (contentHeightPix > heightSize);
mHeightMeasurementLimit = heightSize;
- final boolean measuredHeightClipped =
- mHeightMeasurementLimited && (contentHeightPix > heightSize);
- if (mHeightMeasurementIsFixed || measuredHeightClipped) {
+ if (mHeightMeasurementIsFixed || mHeightMeasurementLimited) {
measuredHeight = heightSize;
}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java
index 1d75dd8..327fcff 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java
@@ -151,6 +151,32 @@
@SmallTest
@Feature({"AndroidWebView"})
+ public void testContentHeightGrowthRequestsLayoutInAtMostSizeMode() {
+ AwLayoutSizer layoutSizer = new AwLayoutSizer();
+ LayoutSizerDelegate delegate = new LayoutSizerDelegate();
+ layoutSizer.setDelegate(delegate);
+ layoutSizer.setDIPScale(DIP_SCALE);
+
+ layoutSizer.onPageScaleChanged(INITIAL_PAGE_SCALE);
+ layoutSizer.onContentSizeChanged(SMALLER_CONTENT_SIZE, SMALLER_CONTENT_SIZE);
+ layoutSizer.onMeasure(
+ MeasureSpec.makeMeasureSpec(AT_MOST_MEASURE_SIZE, MeasureSpec.AT_MOST),
+ MeasureSpec.makeMeasureSpec(AT_MOST_MEASURE_SIZE, MeasureSpec.AT_MOST));
+ assertEquals(AT_MOST_MEASURE_SIZE, delegate.measuredWidth);
+ assertEquals(SMALLER_CONTENT_SIZE, delegate.measuredHeight);
+
+ int requestLayoutCallCount = delegate.requestLayoutCallCount;
+ layoutSizer.onContentSizeChanged(SMALLER_CONTENT_SIZE, AT_MOST_MEASURE_SIZE - 1);
+ assertEquals(requestLayoutCallCount + 1, delegate.requestLayoutCallCount);
+
+ // Test that crossing the AT_MOST_MEASURE_SIZE threshold results in a requestLayout.
+ requestLayoutCallCount = delegate.requestLayoutCallCount;
+ layoutSizer.onContentSizeChanged(SMALLER_CONTENT_SIZE, AT_MOST_MEASURE_SIZE + 1);
+ assertEquals(requestLayoutCallCount + 1, delegate.requestLayoutCallCount);
+ }
+
+ @SmallTest
+ @Feature({"AndroidWebView"})
public void testContentHeightShrinksAfterAtMostSize() {
AwLayoutSizer layoutSizer = new AwLayoutSizer();
LayoutSizerDelegate delegate = new LayoutSizerDelegate();
diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc
index c54fd62..0fa56df 100644
--- a/android_webview/native/aw_contents.cc
+++ b/android_webview/native/aw_contents.cc
@@ -40,7 +40,6 @@
#include "components/autofill/content/browser/autofill_driver_impl.h"
#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
-#include "components/navigation_interception/intercept_navigation_delegate.h"
#include "content/public/browser/android/content_view_core.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cert_store.h"
@@ -73,7 +72,6 @@
using base::android::JavaRef;
using base::android::ScopedJavaGlobalRef;
using base::android::ScopedJavaLocalRef;
-using navigation_interception::InterceptNavigationDelegate;
using content::BrowserThread;
using content::ContentViewCore;
using content::WebContents;
@@ -204,8 +202,7 @@
jobject aw_contents,
jobject web_contents_delegate,
jobject contents_client_bridge,
- jobject io_thread_client,
- jobject intercept_navigation_delegate) {
+ jobject io_thread_client) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// The |aw_content| param is technically spurious as it duplicates |obj| but
// is passed over anyway to make the binding more explicit.
@@ -225,12 +222,6 @@
int child_id = web_contents_->GetRenderProcessHost()->GetID();
int route_id = web_contents_->GetRoutingID();
AwResourceDispatcherHostDelegate::OnIoThreadClientReady(child_id, route_id);
-
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- InterceptNavigationDelegate::Associate(
- web_contents_.get(),
- make_scoped_ptr(new InterceptNavigationDelegate(
- env, intercept_navigation_delegate)));
}
void AwContents::SetSaveFormData(bool enabled) {
@@ -307,8 +298,11 @@
}
void AwContents::Destroy(JNIEnv* env, jobject obj) {
- delete this;
-
+ java_ref_.reset();
+ // We do not delete AwContents immediately. Some applications try to delete
+ // Webview in ShouldOverrideUrlLoading callback, which is a sync IPC from
+ // Webkit.
+ BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this);
// When the last WebView is destroyed free all discardable memory allocated by
// Chromium, because the app process may continue to run for a long time
// without ever using another WebView.
@@ -701,6 +695,12 @@
void AwContents::SetIsPaused(JNIEnv* env, jobject obj, bool paused) {
browser_view_renderer_->SetIsPaused(paused);
+ if (paused) {
+ ContentViewCore* cvc =
+ ContentViewCore::FromWebContents(web_contents_.get());
+ if (cvc)
+ cvc->PauseVideo();
+ }
}
void AwContents::OnAttachedToWindow(JNIEnv* env, jobject obj, int w, int h) {
@@ -868,6 +868,16 @@
env, obj.obj(), contents_size.width(), contents_size.height());
}
+bool AwContents::OnShouldOverrideUrlLoading(const base::string16& url) {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (obj.is_null())
+ return false;
+ ScopedJavaLocalRef<jstring> jurl = ConvertUTF16ToJavaString(env, url);
+ return Java_AwContents_onShouldOverrideUrlLoading(env, obj.obj(),
+ jurl.obj());
+}
+
jint AwContents::CapturePicture(JNIEnv* env,
jobject obj,
int width,
diff --git a/android_webview/native/aw_contents.h b/android_webview/native/aw_contents.h
index aef1fed..6ee4764 100644
--- a/android_webview/native/aw_contents.h
+++ b/android_webview/native/aw_contents.h
@@ -79,8 +79,7 @@
jobject aw_contents,
jobject web_contents_delegate,
jobject contents_client_bridge,
- jobject io_thread_client,
- jobject intercept_navigation_delegate);
+ jobject io_thread_client);
jint GetWebContents(JNIEnv* env, jobject obj);
jint GetAwContentsClientBridge(JNIEnv* env, jobject obj);
@@ -158,6 +157,7 @@
float page_scale_factor) OVERRIDE;
virtual void OnWebLayoutContentsSizeChanged(
const gfx::Size& contents_size) OVERRIDE;
+ virtual bool OnShouldOverrideUrlLoading(const base::string16& url) OVERRIDE;
// BrowserViewRenderer::Client implementation.
virtual bool RequestDrawGL(jobject canvas) OVERRIDE;
diff --git a/android_webview/native/input_stream_impl.cc b/android_webview/native/input_stream_impl.cc
index 24d7be0..fca6a29 100644
--- a/android_webview/native/input_stream_impl.cc
+++ b/android_webview/native/input_stream_impl.cc
@@ -84,46 +84,48 @@
return false;
}
+ int remaining_length = length;
+ char* dest_write_ptr = dest->data();
jbyteArray buffer = buffer_.obj();
*bytes_read = 0;
- const int read_size = std::min(length, kBufferSize);
- int32_t byte_count;
- do {
- // Unfortunately it is valid for the Java InputStream to read 0 bytes some
- // number of times before returning any more data. Because this method
- // signals EOF by setting |bytes_read| to 0 and returning true necessary to
- // call the Java-side read method until it returns something other than 0.
- byte_count = Java_InputStream_readI_AB_I_I(
- env, jobject_.obj(), buffer, 0, read_size);
+ while (remaining_length > 0) {
+ const int max_transfer_length = std::min(remaining_length, kBufferSize);
+ const int transfer_length = Java_InputStream_readI_AB_I_I(
+ env, jobject_.obj(), buffer, 0, max_transfer_length);
if (ClearException(env))
return false;
- } while (byte_count == 0);
- // We've reached the end of the stream.
- if (byte_count < 0)
- return true;
+ if (transfer_length < 0) // EOF
+ break;
-#ifndef NDEBUG
- int32_t buffer_length = env->GetArrayLength(buffer);
- DCHECK_GE(read_size, byte_count);
- DCHECK_GE(buffer_length, byte_count);
-#endif // NDEBUG
+ // Note: it is possible, yet unlikely, that the Java InputStream returns
+ // a transfer_length == 0 from time to time. In such cases we just continue
+ // the read until we get either valid data or reach EOF.
+ if (transfer_length == 0)
+ continue;
- // The DCHECKs are in place to help Chromium developers in case of bugs,
- // this check is to prevent a malicious InputStream implementation from
- // overrunning the |dest| buffer.
- if (byte_count > read_size)
- return false;
+ DCHECK_GE(max_transfer_length, transfer_length);
+ DCHECK_GE(env->GetArrayLength(buffer), transfer_length);
- // Copy the data over to the provided C++ side buffer.
- DCHECK_GE(length, byte_count);
- env->GetByteArrayRegion(buffer, 0, byte_count,
- reinterpret_cast<jbyte*>(dest->data() + *bytes_read));
- if (ClearException(env))
- return false;
+ // This check is to prevent a malicious InputStream implementation from
+ // overrunning the |dest| buffer.
+ if (transfer_length > max_transfer_length)
+ return false;
- *bytes_read = byte_count;
+ // Copy the data over to the provided C++ IOBuffer.
+ DCHECK_GE(remaining_length, transfer_length);
+ env->GetByteArrayRegion(buffer, 0, transfer_length,
+ reinterpret_cast<jbyte*>(dest_write_ptr));
+ if (ClearException(env))
+ return false;
+
+ remaining_length -= transfer_length;
+ dest_write_ptr += transfer_length;
+ }
+ // bytes_read can be strictly less than the req. length if EOF is encountered.
+ DCHECK(remaining_length >= 0 && remaining_length <= length);
+ *bytes_read = length - remaining_length;
return true;
}
diff --git a/android_webview/native/input_stream_unittest.cc b/android_webview/native/input_stream_unittest.cc
index 87b3fe3..76ca823 100644
--- a/android_webview/native/input_stream_unittest.cc
+++ b/android_webview/native/input_stream_unittest.cc
@@ -89,10 +89,10 @@
}
TEST_F(InputStreamTest, TryReadMoreThanBuffer) {
- const int bytes_requested = 3 * InputStreamImpl::kBufferSize;
+ const int buffer_size = 3 * InputStreamImpl::kBufferSize;
int bytes_read = 0;
- DoReadCountedStreamTest(bytes_requested, bytes_requested, &bytes_read);
- EXPECT_EQ(InputStreamImpl::kBufferSize, bytes_read);
+ DoReadCountedStreamTest(buffer_size, buffer_size * 2, &bytes_read);
+ EXPECT_EQ(buffer_size, bytes_read);
}
TEST_F(InputStreamTest, CheckContentsReadCorrectly) {
@@ -105,3 +105,17 @@
EXPECT_EQ(i, (unsigned char)buffer->data()[i]);
}
}
+
+TEST_F(InputStreamTest, ReadLargeStreamPartial) {
+ const int bytes_requested = 3 * InputStreamImpl::kBufferSize;
+ int bytes_read = 0;
+ DoReadCountedStreamTest(bytes_requested + 32, bytes_requested, &bytes_read);
+ EXPECT_EQ(bytes_requested, bytes_read);
+}
+
+TEST_F(InputStreamTest, ReadLargeStreamCompletely) {
+ const int bytes_requested = 3 * InputStreamImpl::kBufferSize;
+ int bytes_read = 0;
+ DoReadCountedStreamTest(bytes_requested, bytes_requested, &bytes_read);
+ EXPECT_EQ(bytes_requested, bytes_read);
+}
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc
index 0ca5212..2419a9b 100644
--- a/android_webview/renderer/aw_content_renderer_client.cc
+++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -5,6 +5,7 @@
#include "android_webview/renderer/aw_content_renderer_client.h"
#include "android_webview/common/aw_resource.h"
+#include "android_webview/common/render_view_messages.h"
#include "android_webview/common/url_constants.h"
#include "android_webview/renderer/aw_render_view_ext.h"
// START: Printing fork b/10190508
@@ -15,12 +16,17 @@
#include "components/autofill/content/renderer/autofill_agent.h"
#include "components/autofill/content/renderer/password_autofill_agent.h"
#include "components/visitedlink/renderer/visitedlink_slave.h"
+#include "content/public/renderer/document_state.h"
+#include "content/public/renderer/navigation_state.h"
#include "content/public/renderer/render_thread.h"
+#include "content/public/renderer/render_view.h"
#include "net/base/net_errors.h"
#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebURLError.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
+#include "third_party/WebKit/public/web/WebNavigationType.h"
#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
#include "url/gurl.h"
@@ -46,6 +52,44 @@
thread->AddObserver(visited_link_slave_.get());
}
+bool AwContentRendererClient::HandleNavigation(
+ content::RenderView* view,
+ content::DocumentState* document_state,
+ WebKit::WebFrame* frame,
+ const WebKit::WebURLRequest& request,
+ WebKit::WebNavigationType type,
+ WebKit::WebNavigationPolicy default_policy,
+ bool is_redirect) {
+
+ // Only GETs can be overridden.
+ if (!request.httpMethod().equals("GET"))
+ return false;
+
+ // Any navigation from loadUrl, and goBack/Forward are considered application-
+ // initiated and hence will not yield a shouldOverrideUrlLoading() callback.
+ // Webview classic does not consider reload application-initiated so we
+ // continue the same behavior.
+ bool application_initiated =
+ !document_state->navigation_state()->is_content_initiated()
+ || type == WebKit::WebNavigationTypeBackForward;
+
+ // Don't offer application-initiated navigations unless it's a redirect.
+ if (application_initiated && !is_redirect)
+ return false;
+
+ // We are only interested in top-level navigation.
+ if (frame->parent())
+ return false;
+
+ bool ignore_navigation = false;
+ int routing_id = view->GetRoutingID();
+ base::string16 url = request.url().string();
+ view->Send (new AwViewHostMsg_ShouldOverrideUrlLoading(routing_id,
+ url,
+ &ignore_navigation));
+ return ignore_navigation;
+}
+
void AwContentRendererClient::RenderViewCreated(
content::RenderView* render_view) {
AwRenderViewExt::RenderViewCreated(render_view);
diff --git a/android_webview/renderer/aw_content_renderer_client.h b/android_webview/renderer/aw_content_renderer_client.h
index 73418d7..36e0c10 100644
--- a/android_webview/renderer/aw_content_renderer_client.h
+++ b/android_webview/renderer/aw_content_renderer_client.h
@@ -10,6 +10,10 @@
#include "android_webview/renderer/aw_render_process_observer.h"
#include "base/compiler_specific.h"
+namespace content {
+class DocumentState;
+class RenderView;
+}
namespace visitedlink {
class VisitedLinkSlave;
}
@@ -37,6 +41,14 @@
size_t length) OVERRIDE;
virtual bool IsLinkVisited(unsigned long long link_hash) OVERRIDE;
+ virtual bool HandleNavigation(content::RenderView* view,
+ content::DocumentState* document_state,
+ WebKit::WebFrame* frame,
+ const WebKit::WebURLRequest& request,
+ WebKit::WebNavigationType type,
+ WebKit::WebNavigationPolicy default_policy,
+ bool is_redirect) OVERRIDE;
+
private:
scoped_ptr<AwRenderProcessObserver> aw_render_process_observer_;
scoped_ptr<visitedlink::VisitedLinkSlave> visited_link_slave_;
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
index 27a50de..ca05938 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -196,6 +196,8 @@
TRACE_EVENT0("cc", "Scheduler::PollForAnticipatedDrawTriggers");
state_machine_.PollForAnticipatedDrawTriggers();
ProcessScheduledActions();
+
+ poll_for_draw_triggers_closure_.Cancel();
}
void Scheduler::DrawAndSwapIfPossible() {
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc
index 7761b35..d9e2b01 100644
--- a/content/browser/android/content_view_core_impl.cc
+++ b/content/browser/android/content_view_core_impl.cc
@@ -342,6 +342,13 @@
void ContentViewCoreImpl::Hide() {
GetWebContents()->WasHidden();
+ PauseVideo();
+}
+
+void ContentViewCoreImpl::PauseVideo() {
+ RenderViewHost* host = web_contents_->GetRenderViewHost();
+ if (host)
+ host->Send(new ViewMsg_PauseVideo(host->GetRoutingID()));
}
void ContentViewCoreImpl::OnTabCrashed() {
diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h
index ffecf2b..a20365b 100644
--- a/content/browser/android/content_view_core_impl.h
+++ b/content/browser/android/content_view_core_impl.h
@@ -60,6 +60,7 @@
virtual float GetDpiScale() const OVERRIDE;
virtual void RequestContentClipping(const gfx::Rect& clipping,
const gfx::Size& content_size) OVERRIDE;
+ virtual void PauseVideo() OVERRIDE;
// --------------------------------------------------------------------------
// Methods called from Java via JNI
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 537aef3..8017069 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -1315,6 +1315,9 @@
// processed on the browser side.
IPC_MESSAGE_ROUTED0(ViewMsg_ImeEventAck)
+// Sent by the browser when we should pause video playback.
+IPC_MESSAGE_ROUTED0(ViewMsg_PauseVideo);
+
#elif defined(OS_MACOSX)
// Let the RenderView know its window has changed visibility.
IPC_MESSAGE_ROUTED1(ViewMsg_SetWindowVisibility,
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
index dace547..c993e85 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
@@ -616,6 +616,8 @@
// If OSK is newly shown, delay the form focus until
// the onSizeChanged (in order to adjust relative to the
// new size).
+ // TODO(jdduke): We should not assume that onSizeChanged will
+ // always be called, crbug.com/294908.
getContainerView().getWindowVisibleDisplayFrame(
mFocusPreOSKViewportRect);
} else if (resultCode ==
@@ -1614,7 +1616,10 @@
Rect rect = new Rect();
getContainerView().getWindowVisibleDisplayFrame(rect);
if (!rect.equals(mFocusPreOSKViewportRect)) {
- scrollFocusedEditableNodeIntoView();
+ // Only assume the OSK triggered the onSizeChanged if width was preserved.
+ if (rect.width() == mFocusPreOSKViewportRect.width()) {
+ scrollFocusedEditableNodeIntoView();
+ }
mFocusPreOSKViewportRect.setEmpty();
}
} else if (mUnfocusOnNextSizeChanged) {
diff --git a/content/public/browser/android/content_view_core.h b/content/public/browser/android/content_view_core.h
index dd3795b..79be4c4 100644
--- a/content/public/browser/android/content_view_core.h
+++ b/content/public/browser/android/content_view_core.h
@@ -54,6 +54,7 @@
virtual float GetDpiScale() const = 0;
virtual void RequestContentClipping(const gfx::Rect& clipping,
const gfx::Size& content_size) = 0;
+ virtual void PauseVideo() = 0;
// Observer callback for frame metadata updates.
typedef base::Callback<void(
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc
index c190f09..a683808 100644
--- a/content/public/renderer/content_renderer_client.cc
+++ b/content/public/renderer/content_renderer_client.cc
@@ -92,6 +92,8 @@
}
bool ContentRendererClient::HandleNavigation(
+ RenderView* view,
+ DocumentState* document_state,
WebKit::WebFrame* frame,
const WebKit::WebURLRequest& request,
WebKit::WebNavigationType type,
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index a00e1a9..549e44d 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -49,6 +49,7 @@
namespace content {
+class DocumentState;
class RenderView;
class SynchronousCompositor;
struct WebPluginInfo;
@@ -167,7 +168,9 @@
// Returns true if the navigation was handled by the embedder and should be
// ignored by WebKit. This method is used by CEF.
- virtual bool HandleNavigation(WebKit::WebFrame* frame,
+ virtual bool HandleNavigation(RenderView* view,
+ DocumentState* document_state,
+ WebKit::WebFrame* frame,
const WebKit::WebURLRequest& request,
WebKit::WebNavigationType type,
WebKit::WebNavigationPolicy default_policy,
diff --git a/content/renderer/media/android/renderer_media_player_manager.cc b/content/renderer/media/android/renderer_media_player_manager.cc
index 47f140f..62a99c0 100644
--- a/content/renderer/media/android/renderer_media_player_manager.cc
+++ b/content/renderer/media/android/renderer_media_player_manager.cc
@@ -33,7 +33,7 @@
media_players_.erase(player_id);
}
-void RendererMediaPlayerManager::ReleaseMediaResources() {
+void RendererMediaPlayerManager::ReleaseVideoResources() {
std::map<int, WebMediaPlayerAndroid*>::iterator player_it;
for (player_it = media_players_.begin();
player_it != media_players_.end(); ++player_it) {
diff --git a/content/renderer/media/android/renderer_media_player_manager.h b/content/renderer/media/android/renderer_media_player_manager.h
index 3e5e13c..e565602 100644
--- a/content/renderer/media/android/renderer_media_player_manager.h
+++ b/content/renderer/media/android/renderer_media_player_manager.h
@@ -32,9 +32,9 @@
int RegisterMediaPlayer(WebMediaPlayerAndroid* player);
void UnregisterMediaPlayer(int player_id);
- // Release all the media resources managed by this object unless
- // an audio play is in progress.
- void ReleaseMediaResources();
+ // Release the media resources managed by this object when a video
+ // is playing.
+ void ReleaseVideoResources();
// Check whether a player can enter fullscreen.
bool CanEnterFullscreen(WebKit::WebFrame* frame);
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index ed8949e..9eb7d57 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -1435,6 +1435,7 @@
OnUndoScrollFocusedEditableNodeIntoRect)
IPC_MESSAGE_HANDLER(ViewMsg_UpdateTopControlsState,
OnUpdateTopControlsState)
+ IPC_MESSAGE_HANDLER(ViewMsg_PauseVideo, OnPauseVideo)
#elif defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(InputMsg_CopyToFindPboard, OnCopyToFindPboard)
IPC_MESSAGE_HANDLER(ViewMsg_PluginImeCompositionCompleted,
@@ -1944,6 +1945,14 @@
if (!node.isNull() && IsEditableNode(node))
webview()->restoreScrollAndScaleState();
}
+
+void RenderViewImpl::OnPauseVideo() {
+ // Inform RendererMediaPlayerManager to release all video player resources.
+ // If something is in progress the resource will not be freed, it will
+ // only be freed once the tab is destroyed or if the user navigates away
+ // via WebMediaPlayerAndroid::Destroy.
+ media_player_manager_->ReleaseVideoResources();
+}
#endif
///////////////////////////////////////////////////////////////////////////////
@@ -3180,9 +3189,13 @@
const WebURLRequest& request, WebNavigationType type,
WebNavigationPolicy default_policy, bool is_redirect) {
if (request.url() != GURL(kSwappedOutURL) &&
- GetContentClient()->renderer()->HandleNavigation(frame, request, type,
- default_policy,
- is_redirect)) {
+ GetContentClient()->renderer()->HandleNavigation(
+ this,
+ static_cast<DocumentState*>(extraData),
+ frame,
+ request, type,
+ default_policy,
+ is_redirect)) {
return WebKit::WebNavigationPolicyIgnore;
}
@@ -5775,19 +5788,10 @@
void RenderViewImpl::OnWasHidden() {
RenderWidget::OnWasHidden();
-#if defined(OS_ANDROID)
- // Inform RendererMediaPlayerManager to release all media player resources.
- // unless some audio is playing.
- // If something is in progress the resource will not be freed, it will
- // only be freed once the tab is destroyed or if the user navigates away
- // via WebMediaPlayerAndroid::Destroy
- media_player_manager_->ReleaseMediaResources();
-
-#if defined(ENABLE_WEBRTC)
+#if defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
RenderThreadImpl::current()->video_capture_impl_manager()->
SuspendDevices(true);
#endif
-#endif
if (webview())
webview()->setVisibilityState(visibilityState(), false);
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 4c6d77a..4464af9 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -1060,6 +1060,8 @@
void OnUpdateTopControlsState(bool enable_hiding,
bool enable_showing,
bool animate);
+ void OnPauseVideo();
+
#elif defined(OS_MACOSX)
void OnCopyToFindPboard();
void OnPluginImeCompositionCompleted(const string16& text, int plugin_id);