summaryrefslogtreecommitdiff
path: root/chromium/content/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/renderer')
-rw-r--r--chromium/content/renderer/render_frame_impl.cc65
-rw-r--r--chromium/content/renderer/render_frame_impl.h8
-rw-r--r--chromium/content/renderer/render_frame_impl_browsertest.cc2
-rw-r--r--chromium/content/renderer/render_widget.cc15
4 files changed, 80 insertions, 10 deletions
diff --git a/chromium/content/renderer/render_frame_impl.cc b/chromium/content/renderer/render_frame_impl.cc
index c75b6177f06..dc3c7420d89 100644
--- a/chromium/content/renderer/render_frame_impl.cc
+++ b/chromium/content/renderer/render_frame_impl.cc
@@ -2427,7 +2427,46 @@ void RenderFrameImpl::OnSwapIn() {
SwapIn();
}
-void RenderFrameImpl::OnDeleteFrame() {
+void RenderFrameImpl::OnDeleteFrame(FrameDeleteIntention intent) {
+ // The main frame (when not provisional) is owned by the renderer's frame tree
+ // via WebViewImpl. When a provisional main frame is swapped in, the ownership
+ // moves from the browser to the renderer, but this happens in the renderer
+ // process and is then the browser is informed.
+ // If the provisional main frame is swapped in while the browser is destroying
+ // it, the browser may request to delete |this|, thinking it has ownership
+ // of it, but the renderer has already taken ownership via SwapIn().
+ switch (intent) {
+ case FrameDeleteIntention::kNotMainFrame:
+ // The frame was not a main frame, so the browser should always have
+ // ownership of it and we can just proceed with deleting it on
+ // request.
+ DCHECK(!is_main_frame_);
+ break;
+ case FrameDeleteIntention::kSpeculativeMainFrameForShutdown:
+ // In this case the renderer has taken ownership of the provisional main
+ // frame but the browser did not know yet and is shutting down. We can
+ // ignore this request as the frame will be destroyed when the RenderView
+ // is. This handles the shutdown case of https://crbug.com/957858.
+ DCHECK(is_main_frame_);
+ if (in_frame_tree_)
+ return;
+ break;
+ case FrameDeleteIntention::kSpeculativeMainFrameForNavigationCancelled:
+ // In this case the browser was navigating and cancelled the speculative
+ // navigation. The renderer *should* undo the SwapIn() but the old state
+ // has already been destroyed. Both ignoring the message or handling it
+ // would leave the renderer in an inconsistent state now. If we ignore it
+ // then the browser thinks the RenderView has a remote main frame, but it
+ // is incorrect. If we handle it, then we are deleting a local main frame
+ // out from under the RenderView and we will have bad pointers in the
+ // renderer. So all we can do is crash. We should instead prevent this
+ // scenario by blocking the browser from dropping the speculative main
+ // frame when a commit (and ownership transfer) is imminent.
+ // TODO(dcheng): This is the case of https://crbug.com/838348.
+ DCHECK(is_main_frame_);
+ break;
+ }
+
// This will result in a call to RenderFrameImpl::FrameDetached, which
// deletes the object. Do not access |this| after detach.
frame_->Detach();
@@ -2508,6 +2547,7 @@ void RenderFrameImpl::OnAddMessageToConsole(
void RenderFrameImpl::JavaScriptExecuteRequest(
const base::string16& javascript,
+ bool wants_result,
JavaScriptExecuteRequestCallback callback) {
TRACE_EVENT_INSTANT0("test_tracing", "JavaScriptExecuteRequest",
TRACE_EVENT_SCOPE_THREAD);
@@ -2522,11 +2562,15 @@ void RenderFrameImpl::JavaScriptExecuteRequest(
if (!weak_this)
return;
- std::move(callback).Run(GetJavaScriptExecutionResult(result));
+ if (wants_result)
+ std::move(callback).Run(GetJavaScriptExecutionResult(result));
+ else
+ std::move(callback).Run({});
}
void RenderFrameImpl::JavaScriptExecuteRequestForTests(
const base::string16& javascript,
+ bool wants_result,
bool has_user_gesture,
JavaScriptExecuteRequestForTestsCallback callback) {
TRACE_EVENT_INSTANT0("test_tracing", "JavaScriptExecuteRequestForTests",
@@ -2548,11 +2592,15 @@ void RenderFrameImpl::JavaScriptExecuteRequestForTests(
if (!weak_this)
return;
- std::move(callback).Run(GetJavaScriptExecutionResult(result));
+ if (wants_result)
+ std::move(callback).Run(GetJavaScriptExecutionResult(result));
+ else
+ std::move(callback).Run({});
}
void RenderFrameImpl::JavaScriptExecuteRequestInIsolatedWorld(
const base::string16& javascript,
+ bool wants_result,
int32_t world_id,
JavaScriptExecuteRequestInIsolatedWorldCallback callback) {
TRACE_EVENT_INSTANT0("test_tracing",
@@ -2571,15 +2619,18 @@ void RenderFrameImpl::JavaScriptExecuteRequestInIsolatedWorld(
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
WebScriptSource script = WebScriptSource(WebString::FromUTF16(javascript));
JavaScriptIsolatedWorldRequest* request = new JavaScriptIsolatedWorldRequest(
- weak_factory_.GetWeakPtr(), std::move(callback));
+ weak_factory_.GetWeakPtr(), wants_result, std::move(callback));
frame_->RequestExecuteScriptInIsolatedWorld(
world_id, &script, 1, false, WebLocalFrame::kSynchronous, request);
}
RenderFrameImpl::JavaScriptIsolatedWorldRequest::JavaScriptIsolatedWorldRequest(
base::WeakPtr<RenderFrameImpl> render_frame_impl,
+ bool wants_result,
JavaScriptExecuteRequestInIsolatedWorldCallback callback)
- : render_frame_impl_(render_frame_impl), callback_(std::move(callback)) {}
+ : render_frame_impl_(render_frame_impl),
+ wants_result_(wants_result),
+ callback_(std::move(callback)) {}
RenderFrameImpl::JavaScriptIsolatedWorldRequest::
~JavaScriptIsolatedWorldRequest() {
@@ -2594,7 +2645,7 @@ void RenderFrameImpl::JavaScriptIsolatedWorldRequest::Completed(
}
base::Value value;
- if (!result.empty()) {
+ if (!result.empty() && wants_result_) {
// It's safe to always use the main world context when converting
// here. V8ValueConverterImpl shouldn't actually care about the
// context scope, and it switches to v8::Object's creation context
@@ -3101,7 +3152,7 @@ void RenderFrameImpl::LoadErrorPage(int reason) {
}
void RenderFrameImpl::ExecuteJavaScript(const base::string16& javascript) {
- JavaScriptExecuteRequest(javascript, base::DoNothing());
+ JavaScriptExecuteRequest(javascript, false, base::DoNothing());
}
void RenderFrameImpl::BindLocalInterface(
diff --git a/chromium/content/renderer/render_frame_impl.h b/chromium/content/renderer/render_frame_impl.h
index 4613ce47c11..d35cfb8dd67 100644
--- a/chromium/content/renderer/render_frame_impl.h
+++ b/chromium/content/renderer/render_frame_impl.h
@@ -34,6 +34,7 @@
#include "content/common/buildflags.h"
#include "content/common/download/mhtml_file_writer.mojom.h"
#include "content/common/frame.mojom.h"
+#include "content/common/frame_delete_intention.h"
#include "content/common/frame_message_enums.h"
#include "content/common/host_zoom.mojom.h"
#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
@@ -637,13 +638,16 @@ class CONTENT_EXPORT RenderFrameImpl
void JavaScriptExecuteRequest(
const base::string16& javascript,
+ bool wants_result,
JavaScriptExecuteRequestCallback callback) override;
void JavaScriptExecuteRequestForTests(
const base::string16& javascript,
+ bool wants_result,
bool has_user_gesture,
JavaScriptExecuteRequestForTestsCallback callback) override;
void JavaScriptExecuteRequestInIsolatedWorld(
const base::string16& javascript,
+ bool wants_result,
int32_t world_id,
JavaScriptExecuteRequestInIsolatedWorldCallback callback) override;
void OnPortalActivated(const base::UnguessableToken& portal_token,
@@ -1029,6 +1033,7 @@ class CONTENT_EXPORT RenderFrameImpl
public:
JavaScriptIsolatedWorldRequest(
base::WeakPtr<RenderFrameImpl> render_frame_impl,
+ bool wants_result,
JavaScriptExecuteRequestInIsolatedWorldCallback callback);
void Completed(
const blink::WebVector<v8::Local<v8::Value>>& result) override;
@@ -1037,6 +1042,7 @@ class CONTENT_EXPORT RenderFrameImpl
~JavaScriptIsolatedWorldRequest() override;
base::WeakPtr<RenderFrameImpl> render_frame_impl_;
+ bool wants_result_;
JavaScriptExecuteRequestInIsolatedWorldCallback callback_;
DISALLOW_COPY_AND_ASSIGN(JavaScriptIsolatedWorldRequest);
@@ -1111,7 +1117,7 @@ class CONTENT_EXPORT RenderFrameImpl
void OnSwapOut(int proxy_routing_id,
bool is_loading,
const FrameReplicationState& replicated_frame_state);
- void OnDeleteFrame();
+ void OnDeleteFrame(FrameDeleteIntention intent);
void OnStop();
void OnCollapse(bool collapse);
void OnShowContextMenu(const gfx::Point& location);
diff --git a/chromium/content/renderer/render_frame_impl_browsertest.cc b/chromium/content/renderer/render_frame_impl_browsertest.cc
index 6772deaa8a0..c994c84d377 100644
--- a/chromium/content/renderer/render_frame_impl_browsertest.cc
+++ b/chromium/content/renderer/render_frame_impl_browsertest.cc
@@ -497,7 +497,7 @@ TEST_F(RenderFrameImplTest, NoCrashWhenDeletingFrameDuringFind) {
1, "foo", true /* match_case */, true /* forward */,
false /* find_next */, true /* force */, false /* wrap_within_frame */);
- FrameMsg_Delete delete_message(0);
+ FrameMsg_Delete delete_message(0, FrameDeleteIntention::kNotMainFrame);
frame()->OnMessageReceived(delete_message);
}
diff --git a/chromium/content/renderer/render_widget.cc b/chromium/content/renderer/render_widget.cc
index 970bdf426ed..24449d77790 100644
--- a/chromium/content/renderer/render_widget.cc
+++ b/chromium/content/renderer/render_widget.cc
@@ -184,6 +184,18 @@ static const int kInvalidNextPreviousFlagsValue = -1;
static const char* kOOPIF = "OOPIF";
static const char* kRenderer = "Renderer";
+#if defined(OS_ANDROID)
+// With 32 bit pixels, this would mean less than 400kb per buffer. Much less
+// than required for, say, nHD.
+static const int kSmallScreenPixelThreshold = 1e5;
+bool IsSmallScreen(const gfx::Size& size) {
+ int area = 0;
+ if (!size.GetCheckedArea().AssignIfValid(&area))
+ return false;
+ return area < kSmallScreenPixelThreshold;
+}
+#endif
+
class WebWidgetLockTarget : public content::MouseLockDispatcher::LockTarget {
public:
explicit WebWidgetLockTarget(blink::WebWidget* webwidget)
@@ -3013,7 +3025,8 @@ cc::LayerTreeSettings RenderWidget::GenerateLayerTreeSettings(
#if defined(OS_ANDROID)
bool using_synchronous_compositor =
compositor_deps->UsingSynchronousCompositing();
- bool using_low_memory_policy = base::SysInfo::IsLowEndDevice();
+ bool using_low_memory_policy =
+ base::SysInfo::IsLowEndDevice() && !IsSmallScreen(screen_size);
settings.use_stream_video_draw_quad = true;
settings.using_synchronous_renderer_compositor = using_synchronous_compositor;