diff options
| author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-05-03 17:20:32 +0200 |
|---|---|---|
| committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-05-05 09:28:09 +0000 |
| commit | bb09965444b5bb20b096a291445170876225268d (patch) | |
| tree | b5f6596f7e6e941b1d7d72f0ce5181500c261529 /chromium/content | |
| parent | 7324afb043a0b1e623d8e8eb906cdc53bdeb4685 (diff) | |
| download | qtwebengine-chromium-bb09965444b5bb20b096a291445170876225268d.tar.gz | |
BASELINE: Update Chromium to 58.0.3029.98
Change-Id: Ib913750d687f29e036959c62a0cabf2412a8faa7
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/content')
33 files changed, 440 insertions, 89 deletions
diff --git a/chromium/content/app/strings/translations/content_strings_es.xtb b/chromium/content/app/strings/translations/content_strings_es.xtb index cff295b99e0..a5abfcf8ac7 100644 --- a/chromium/content/app/strings/translations/content_strings_es.xtb +++ b/chromium/content/app/strings/translations/content_strings_es.xtb @@ -6,7 +6,7 @@ <translation id="10623998915015855">botón de activación</translation> <translation id="1088086359088493902">Segundos</translation> <translation id="1171774979989969504">Introduce una dirección de correo electrónico</translation> -<translation id="1178581264944972037">Detener</translation> +<translation id="1178581264944972037">Pausar</translation> <translation id="1188858454923323853">complementario</translation> <translation id="1206619573307042055">marquee</translation> <translation id="1206693055195146388">control deslizante</translation> diff --git a/chromium/content/browser/android/date_time_chooser_android.cc b/chromium/content/browser/android/date_time_chooser_android.cc index ba20ad53bd5..2ea331c5502 100644 --- a/chromium/content/browser/android/date_time_chooser_android.cc +++ b/chromium/content/browser/android/date_time_chooser_android.cc @@ -92,9 +92,13 @@ void DateTimeChooserAndroid::ShowDialog( } } - j_date_time_chooser_.Reset(Java_DateTimeChooserAndroid_createDateTimeChooser( - env, native_window->GetJavaObject(), reinterpret_cast<intptr_t>(this), - dialog_type, dialog_value, min, max, step, suggestions_array)); + if (native_window && !(native_window->GetJavaObject()).is_null()) { + j_date_time_chooser_.Reset( + Java_DateTimeChooserAndroid_createDateTimeChooser( + env, native_window->GetJavaObject(), + reinterpret_cast<intptr_t>(this), dialog_type, dialog_value, min, + max, step, suggestions_array)); + } if (j_date_time_chooser_.is_null()) ReplaceDateTime(env, j_date_time_chooser_, dialog_value); } diff --git a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc index e0464b67354..3a0e0915ad7 100644 --- a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc +++ b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc @@ -63,7 +63,7 @@ bool GpuSurfacelessBrowserCompositorOutputSurface::IsDisplayedAsOverlayPlane() unsigned GpuSurfacelessBrowserCompositorOutputSurface::GetOverlayTextureId() const { - return buffer_queue_->current_texture_id(); + return buffer_queue_->GetCurrentTextureId(); } void GpuSurfacelessBrowserCompositorOutputSurface::SwapBuffers( @@ -73,8 +73,15 @@ void GpuSurfacelessBrowserCompositorOutputSurface::SwapBuffers( // TODO(ccameron): What if a swap comes again before OnGpuSwapBuffersCompleted // happens, we'd see the wrong swap size there? swap_size_ = reshape_size_; - buffer_queue_->SwapBuffers(frame.sub_buffer_rect ? *frame.sub_buffer_rect - : gfx::Rect(swap_size_)); + + gfx::Rect damage_rect = + frame.sub_buffer_rect ? *frame.sub_buffer_rect : gfx::Rect(swap_size_); + // Use previous buffer when damage rect is empty. This avoids unnecessary + // partial swap work and makes it possible to support empty swaps on devices + // where partial swaps are disabled. + if (!damage_rect.IsEmpty()) + buffer_queue_->SwapBuffers(damage_rect); + GpuBrowserCompositorOutputSurface::SwapBuffers(std::move(frame)); } diff --git a/chromium/content/browser/find_request_manager.cc b/chromium/content/browser/find_request_manager.cc index 5c2eeb2df37..7713bc3a5b9 100644 --- a/chromium/content/browser/find_request_manager.cc +++ b/chromium/content/browser/find_request_manager.cc @@ -158,9 +158,13 @@ void FindRequestManager::OnFindReply(RenderFrameHost* rfh, number_of_matches_ += matches_delta; matches_per_frame_it->second = number_of_matches; + // All matches may have been removed since the last find reply. + if (rfh == active_frame_ && !number_of_matches) + relative_active_match_ordinal_ = 0; + // The active match ordinal may need updating since the number of matches // before the active match may have changed. - if (rfh != active_frame_) + if (rfh != active_frame_ || !number_of_matches) UpdateActiveMatchOrdinal(); } } diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.cc b/chromium/content/browser/frame_host/navigation_handle_impl.cc index 380b80a125a..4ebe13f190b 100644 --- a/chromium/content/browser/frame_host/navigation_handle_impl.cc +++ b/chromium/content/browser/frame_host/navigation_handle_impl.cc @@ -947,6 +947,12 @@ bool NavigationHandleImpl::IsSelfReferentialURL() { if (!is_renderer_initiated_) return false; + // Some sites rely on constructing frame hierarchies where frames are loaded + // via POSTs with the same URLs, so exempt POST requests. See + // https://crbug.com/710008. + if (method_ == "POST") + return false; + // We allow one level of self-reference because some sites depend on that, // but we don't allow more than one. bool found_self_reference = false; diff --git a/chromium/content/browser/frame_host/render_frame_host_manager.cc b/chromium/content/browser/frame_host/render_frame_host_manager.cc index 120595fdc6b..1bbf60fac4e 100644 --- a/chromium/content/browser/frame_host/render_frame_host_manager.cc +++ b/chromium/content/browser/frame_host/render_frame_host_manager.cc @@ -2327,6 +2327,13 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate( dest_url, source_instance, dest_instance, nullptr, transition, dest_is_restore, dest_is_view_source_mode, was_server_redirect); + // Note: Do not add code here to determine whether the subframe should swap + // or not. Add it to CanSubframeSwapProcess instead. + bool allowed_to_swap_process = + frame_tree_node_->IsMainFrame() || + CanSubframeSwapProcess(dest_url, source_instance, dest_instance, + was_server_redirect); + // Inform the transferring NavigationHandle of a transfer to a different // SiteInstance. It is important do so now, in order to mark the request as // transferring on the IO thread before attempting to destroy the pending RFH. @@ -2334,11 +2341,22 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate( // RFH but will persist until it is picked up by the new RFH. if (transfer_navigation_handle_.get() && transfer_navigation_handle_->GetGlobalRequestID() == - transferred_request_id && - new_instance.get() != - transfer_navigation_handle_->GetRenderFrameHost() - ->GetSiteInstance()) { - transfer_navigation_handle_->Transfer(); + transferred_request_id) { + // The transfer is needed when switching to a new SiteInstance. One + // exception is if the process swap is not allowed and the transfer started + // in the current RFH, the navigation will stay in the current RFH (even + // when there is a new SiteInstance), so avoid calling Transfer() on it. + // This matters for some renderer-initiated data URLs navigations, see + // https://crbug.com/697513. + RenderFrameHostImpl* transferring_rfh = + transfer_navigation_handle_->GetRenderFrameHost(); + bool transfer_started_from_current_rfh = + transferring_rfh == render_frame_host_.get(); + bool should_transfer = + new_instance.get() != transferring_rfh->GetSiteInstance() && + (!transfer_started_from_current_rfh || allowed_to_swap_process); + if (should_transfer) + transfer_navigation_handle_->Transfer(); } // If we are currently navigating cross-process to a pending RFH for a @@ -2355,13 +2373,6 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate( } } - // Note: Do not add code here to determine whether the subframe should swap - // or not. Add it to CanSubframeSwapProcess instead. - bool allowed_to_swap_process = - frame_tree_node_->IsMainFrame() || - CanSubframeSwapProcess(dest_url, source_instance, dest_instance, - was_server_redirect); - if (new_instance.get() != current_instance && allowed_to_swap_process) { TRACE_EVENT_INSTANT2( "navigation", diff --git a/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc index 02027b0ee6d..74bb5be539a 100644 --- a/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc +++ b/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc @@ -3272,4 +3272,53 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, EXPECT_EQ(child->current_url(), first_url); } +// Ensures that POST requests bypass self-referential URL checks. See +// https://crbug.com/710008. +IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, + SelfReferencingFramesWithPOST) { + StartEmbeddedServer(); + GURL url(embedded_test_server()->GetURL("a.com", "/page_with_iframe.html")); + EXPECT_TRUE(NavigateToURL(shell(), url)); + + WebContentsImpl* web_contents = + static_cast<WebContentsImpl*>(shell()->web_contents()); + + FrameTreeNode* root = web_contents->GetFrameTree()->root(); + FrameTreeNode* child = root->child_at(0); + + GURL child_url(embedded_test_server()->GetURL("a.com", "/title1.html")); + EXPECT_EQ(url, root->current_url()); + EXPECT_EQ(child_url, child->current_url()); + + // Navigate the child frame to the same URL as parent via POST. + std::string script = + "var f = document.createElement('form');\n" + "f.method = 'POST';\n" + "f.action = '/page_with_iframe.html';\n" + "document.body.appendChild(f);\n" + "f.submit();"; + { + TestFrameNavigationObserver observer(child); + EXPECT_TRUE(ExecuteScript(child, script)); + observer.Wait(); + } + + FrameTreeNode* grandchild = child->child_at(0); + EXPECT_EQ(url, child->current_url()); + EXPECT_EQ(child_url, grandchild->current_url()); + + // Now navigate the grandchild to the same URL as its two ancestors. This + // should be allowed since it uses POST; it was blocked prior to + // fixing https://crbug.com/710008. + { + TestFrameNavigationObserver observer(grandchild); + EXPECT_TRUE(ExecuteScript(grandchild, script)); + observer.Wait(); + } + + EXPECT_EQ(url, grandchild->current_url()); + ASSERT_EQ(1U, grandchild->child_count()); + EXPECT_EQ(child_url, grandchild->child_at(0)->current_url()); +} + } // namespace content diff --git a/chromium/content/browser/gpu/gpu_process_host.cc b/chromium/content/browser/gpu/gpu_process_host.cc index a3860fed97a..f1544f496c3 100644 --- a/chromium/content/browser/gpu/gpu_process_host.cc +++ b/chromium/content/browser/gpu/gpu_process_host.cc @@ -445,6 +445,14 @@ void GpuProcessHost::CallOnIO( base::Bind(&RunCallbackOnIO, kind, force_create, callback)); } +GpuProcessHost::EstablishChannelRequest::EstablishChannelRequest() + : client_id(0) {} + +GpuProcessHost::EstablishChannelRequest::EstablishChannelRequest( + const EstablishChannelRequest& other) = default; + +GpuProcessHost::EstablishChannelRequest::~EstablishChannelRequest() {} + service_manager::InterfaceProvider* GpuProcessHost::GetRemoteInterfaces() { return process_->child_connection()->GetRemoteInterfaces(); } @@ -470,8 +478,7 @@ GpuProcessHost::GpuProcessHost(int host_id, GpuProcessKind kind) kind_(kind), process_launched_(false), initialized_(false), - gpu_host_binding_(this), - weak_ptr_factory_(this) { + gpu_host_binding_(this) { if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kSingleProcess) || base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -680,6 +687,7 @@ bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) { DCHECK(CalledOnValidThread()); IPC_BEGIN_MESSAGE_MAP(GpuProcessHost, message) IPC_MESSAGE_HANDLER(GpuHostMsg_Initialized, OnInitialized) + IPC_MESSAGE_HANDLER(GpuHostMsg_ChannelEstablished, OnChannelEstablished) IPC_MESSAGE_HANDLER(GpuHostMsg_GpuMemoryBufferCreated, OnGpuMemoryBufferCreated) #if defined(OS_ANDROID) @@ -719,15 +727,21 @@ void GpuProcessHost::EstablishGpuChannel( return; } - DCHECK_EQ(preempts, allow_view_command_buffers); - DCHECK_EQ(preempts, allow_real_time_streams); - bool is_gpu_host = preempts; - - channel_requests_.push(callback); - gpu_service_ptr_->EstablishGpuChannel( - client_id, client_tracing_id, is_gpu_host, - base::Bind(&GpuProcessHost::OnChannelEstablished, - weak_ptr_factory_.GetWeakPtr(), client_id, callback)); + EstablishChannelParams params; + params.client_id = client_id; + params.client_tracing_id = client_tracing_id; + params.preempts = preempts; + params.allow_view_command_buffers = allow_view_command_buffers; + params.allow_real_time_streams = allow_real_time_streams; + if (Send(new GpuMsg_EstablishChannel(params))) { + EstablishChannelRequest request; + request.client_id = client_id; + request.callback = callback; + channel_requests_.push(request); + } else { + DVLOG(1) << "Failed to send GpuMsg_EstablishChannel."; + callback.Run(IPC::ChannelHandle(), gpu::GPUInfo()); + } if (!base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableGpuShaderDiskCache)) { @@ -802,27 +816,32 @@ void GpuProcessHost::OnInitialized( } void GpuProcessHost::OnChannelEstablished( - int client_id, - const EstablishChannelCallback& callback, - mojo::ScopedMessagePipeHandle channel_handle) { + const IPC::ChannelHandle& channel_handle) { TRACE_EVENT0("gpu", "GpuProcessHost::OnChannelEstablished"); - DCHECK(!channel_requests_.empty()); - DCHECK(channel_requests_.front().Equals(callback)); + + if (channel_requests_.empty()) { + // This happens when GPU process is compromised. + RouteOnUIThread(GpuHostMsg_OnLogMessage( + logging::LOG_WARNING, "WARNING", + "Received a ChannelEstablished message but no requests in queue.")); + return; + } + EstablishChannelRequest request = channel_requests_.front(); channel_requests_.pop(); // Currently if any of the GPU features are blacklisted, we don't establish a // GPU channel. - if (channel_handle.is_valid() && - !GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(nullptr)) { - Send(new GpuMsg_CloseChannel(client_id)); - callback.Run(IPC::ChannelHandle(), gpu::GPUInfo()); + if (channel_handle.mojo_handle.is_valid() && + !GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(NULL)) { + Send(new GpuMsg_CloseChannel(request.client_id)); + request.callback.Run(IPC::ChannelHandle(), gpu::GPUInfo()); RouteOnUIThread( GpuHostMsg_OnLogMessage(logging::LOG_WARNING, "WARNING", "Hardware acceleration is unavailable.")); return; } - callback.Run(IPC::ChannelHandle(channel_handle.release()), gpu_info_); + request.callback.Run(channel_handle, gpu_info_); } void GpuProcessHost::OnGpuMemoryBufferCreated( @@ -1082,12 +1101,11 @@ bool GpuProcessHost::LaunchGpuProcess(gpu::GpuPreferences* gpu_preferences) { void GpuProcessHost::SendOutstandingReplies() { valid_ = false; - // First send empty channel handles for all EstablishChannel requests. while (!channel_requests_.empty()) { - auto callback = channel_requests_.front(); + EstablishChannelRequest request = channel_requests_.front(); channel_requests_.pop(); - callback.Run(IPC::ChannelHandle(), gpu::GPUInfo()); + request.callback.Run(IPC::ChannelHandle(), gpu::GPUInfo()); } while (!create_gpu_memory_buffer_requests_.empty()) { diff --git a/chromium/content/browser/gpu/gpu_process_host.h b/chromium/content/browser/gpu/gpu_process_host.h index 101b8d4ed85..9cb6f5831f0 100644 --- a/chromium/content/browser/gpu/gpu_process_host.h +++ b/chromium/content/browser/gpu/gpu_process_host.h @@ -72,6 +72,14 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, typedef base::Callback<void(const IPC::ChannelHandle&, const gpu::GPUInfo&)> EstablishChannelCallback; + struct EstablishChannelRequest { + EstablishChannelRequest(); + EstablishChannelRequest(const EstablishChannelRequest& other); + ~EstablishChannelRequest(); + int32_t client_id; + EstablishChannelCallback callback; + }; + typedef base::Callback<void(const gfx::GpuMemoryBufferHandle& handle)> CreateGpuMemoryBufferCallback; @@ -197,14 +205,11 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, const std::string& key, const std::string& shader) override; - void OnChannelEstablished(int client_id, - const EstablishChannelCallback& callback, - mojo::ScopedMessagePipeHandle channel_handle); - // Message handlers. void OnInitialized(bool result, const gpu::GPUInfo& gpu_info, const gpu::GpuFeatureInfo& gpu_feature_info); + void OnChannelEstablished(const IPC::ChannelHandle& channel_handle); void OnGpuMemoryBufferCreated(const gfx::GpuMemoryBufferHandle& handle); #if defined(OS_ANDROID) void OnDestroyingVideoSurfaceAck(int surface_id); @@ -229,7 +234,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, // These are the channel requests that we have already sent to // the GPU process, but haven't heard back about yet. - std::queue<EstablishChannelCallback> channel_requests_; + std::queue<EstablishChannelRequest> channel_requests_; // The pending create gpu memory buffer requests we need to reply to. std::queue<CreateGpuMemoryBufferCallback> create_gpu_memory_buffer_requests_; @@ -296,8 +301,6 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, ui::mojom::GpuServicePtr gpu_service_ptr_; mojo::Binding<ui::mojom::GpuHost> gpu_host_binding_; - base::WeakPtrFactory<GpuProcessHost> weak_ptr_factory_; - DISALLOW_COPY_AND_ASSIGN(GpuProcessHost); }; diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc index 3e200a25cd7..7dff16b1a90 100644 --- a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc @@ -1329,7 +1329,8 @@ void ResourceDispatcherHostImpl::BeginRequest( } ContinuePendingBeginRequest( requester_info, request_id, request_data, sync_result_handler, route_id, - headers, std::move(mojo_request), std::move(url_loader_client), true, 0); + headers, std::move(mojo_request), std::move(url_loader_client), + HeaderInterceptorResult::CONTINUE); } void ResourceDispatcherHostImpl::ContinuePendingBeginRequest( @@ -1341,13 +1342,14 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest( const net::HttpRequestHeaders& headers, mojom::URLLoaderAssociatedRequest mojo_request, mojom::URLLoaderClientPtr url_loader_client, - bool continue_request, - int error_code) { + HeaderInterceptorResult interceptor_result) { DCHECK(requester_info->IsRenderer() || requester_info->IsNavigationPreload()); - if (!continue_request) { - if (requester_info->IsRenderer()) { + if (interceptor_result != HeaderInterceptorResult::CONTINUE) { + if (requester_info->IsRenderer() && + interceptor_result == HeaderInterceptorResult::KILL) { // TODO(ananta): Find a way to specify the right error code here. Passing - // in a non-content error code is not safe. + // in a non-content error code is not safe, but future header interceptors + // might say to kill for reasons other than illegal origins. bad_message::ReceivedBadMessage(requester_info->filter(), bad_message::RDH_ILLEGAL_ORIGIN); } diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.h b/chromium/content/browser/loader/resource_dispatcher_host_impl.h index c30b304c738..13b0378ad65 100644 --- a/chromium/content/browser/loader/resource_dispatcher_host_impl.h +++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.h @@ -583,9 +583,8 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl // decisions which could be time consuming. We allow for these decisions // to be made asynchronously. The request proceeds when we hear back from // the interceptors about whether to continue or not. - // The |continue_request| parameter in the function indicates whether the - // request should be continued or aborted. The |error_code| parameter is set - // if |continue_request| is false. + // The |interceptor_result| indicates whether the request should be continued + // or aborted, and in the latter case whether the renderer should be killed. void ContinuePendingBeginRequest( scoped_refptr<ResourceRequesterInfo> requester_info, int request_id, @@ -595,8 +594,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl const net::HttpRequestHeaders& headers, mojom::URLLoaderAssociatedRequest mojo_request, mojom::URLLoaderClientPtr url_loader_client, - bool continue_request, - int error_code); + HeaderInterceptorResult interceptor_result); // Creates a ResourceHandler to be used by BeginRequest() for normal resource // loading. diff --git a/chromium/content/browser/media/android/media_player_renderer.cc b/chromium/content/browser/media/android/media_player_renderer.cc index 7e5874aedd2..9c129c6cba3 100644 --- a/chromium/content/browser/media/android/media_player_renderer.cc +++ b/chromium/content/browser/media/android/media_player_renderer.cc @@ -32,7 +32,6 @@ media::MediaUrlInterceptor* g_media_url_interceptor = nullptr; MediaPlayerRenderer::MediaPlayerRenderer(RenderFrameHost* render_frame_host) : render_frame_host_(render_frame_host), - duration_(media::kInfiniteDuration), has_error_(false), weak_factory_(this) {} diff --git a/chromium/content/browser/pointer_lock_browsertest.cc b/chromium/content/browser/pointer_lock_browsertest.cc index 46fde73b719..ad5e90c7b3a 100644 --- a/chromium/content/browser/pointer_lock_browsertest.cc +++ b/chromium/content/browser/pointer_lock_browsertest.cc @@ -307,4 +307,115 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockChildFrameDetached) { web_contents()->GetMouseLockWidget()); } +IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWheelEventRouting) { + GURL main_url(embedded_test_server()->GetURL( + "a.com", "/cross_site_iframe_factory.html?a(b)")); + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + + FrameTreeNode* root = web_contents()->GetFrameTree()->root(); + FrameTreeNode* child = root->child_at(0); + RenderWidgetHostInputEventRouter* router = + web_contents()->GetInputEventRouter(); + RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>( + root->current_frame_host()->GetView()); + RenderWidgetHostViewBase* child_view = static_cast<RenderWidgetHostViewBase*>( + child->current_frame_host()->GetView()); + + // Request a pointer lock on the root frame's body. + EXPECT_TRUE(ExecuteScript(root, "document.body.requestPointerLock()")); + + // Root frame should have been granted pointer lock. + bool locked = false; + EXPECT_TRUE(ExecuteScriptAndExtractBool(root, + "window.domAutomationController.send(" + "document.pointerLockElement == " + "document.body);", + &locked)); + EXPECT_TRUE(locked); + + // Add a mouse move wheel event listener to the root frame. + EXPECT_TRUE(ExecuteScript( + root, + "var x; var y; var mX; var mY; document.addEventListener('mousewheel', " + "function(e) {x = e.x; y = e.y; dX = e.deltaX; dY = e.deltaY;});")); + MainThreadFrameObserver root_observer(root_view->GetRenderWidgetHost()); + root_observer.Wait(); + + blink::WebMouseWheelEvent wheel_event( + blink::WebInputEvent::MouseWheel, blink::WebInputEvent::NoModifiers, + blink::WebInputEvent::TimeStampForTesting); + wheel_event.x = 10; + wheel_event.y = 11; + wheel_event.deltaX = -12; + wheel_event.deltaY = -13; + router->RouteMouseWheelEvent(root_view, &wheel_event, ui::LatencyInfo()); + + // Make sure that the renderer handled the input event. + root_observer.Wait(); + + int x, y, deltaX, deltaY; + EXPECT_TRUE(ExecuteScriptAndExtractInt( + root, "window.domAutomationController.send(x);", &x)); + EXPECT_TRUE(ExecuteScriptAndExtractInt( + root, "window.domAutomationController.send(y);", &y)); + EXPECT_TRUE(ExecuteScriptAndExtractInt( + root, "window.domAutomationController.send(dX);", &deltaX)); + EXPECT_TRUE(ExecuteScriptAndExtractInt( + root, "window.domAutomationController.send(dY);", &deltaY)); + EXPECT_EQ(10, x); + EXPECT_EQ(11, y); + EXPECT_EQ(12, deltaX); + EXPECT_EQ(13, deltaY); + + // Release pointer lock on root frame. + EXPECT_TRUE(ExecuteScript(root, "document.exitPointerLock()")); + + // Request a pointer lock on the child frame's body. + EXPECT_TRUE(ExecuteScript(child, "document.body.requestPointerLock()")); + + // Child frame should have been granted pointer lock. + EXPECT_TRUE(ExecuteScriptAndExtractBool(child, + "window.domAutomationController.send(" + "document.pointerLockElement == " + "document.body);", + &locked)); + EXPECT_TRUE(locked); + + // Add a mouse move event listener to the child frame. + EXPECT_TRUE(ExecuteScript( + child, + "var x; var y; var mX; var mY; document.addEventListener('mousewheel', " + "function(e) {x = e.x; y = e.y; dX = e.deltaX; dY = e.deltaY;});")); + MainThreadFrameObserver child_observer(child_view->GetRenderWidgetHost()); + child_observer.Wait(); + + gfx::Point transformed_point; + root_view->TransformPointToCoordSpaceForView(gfx::Point(0, 0), child_view, + &transformed_point); + + wheel_event.x = -transformed_point.x() + 14; + wheel_event.y = -transformed_point.y() + 15; + wheel_event.deltaX = -16; + wheel_event.deltaY = -17; + // We use root_view intentionally as the RenderWidgetHostInputEventRouter is + // responsible for correctly routing the event to the child frame. + router->RouteMouseWheelEvent(root_view, &wheel_event, ui::LatencyInfo()); + + // Make sure that the renderer handled the input event. + child_observer.Wait(); + + EXPECT_TRUE(ExecuteScriptAndExtractInt( + child, "window.domAutomationController.send(x);", &x)); + EXPECT_TRUE(ExecuteScriptAndExtractInt( + child, "window.domAutomationController.send(y);", &y)); + EXPECT_TRUE(ExecuteScriptAndExtractInt( + child, "window.domAutomationController.send(dX);", &deltaX)); + EXPECT_TRUE(ExecuteScriptAndExtractInt( + child, "window.domAutomationController.send(dY);", &deltaY)); + EXPECT_EQ(14, x); + EXPECT_EQ(15, y); + EXPECT_EQ(16, deltaX); + EXPECT_EQ(17, deltaY); +} + } // namespace content diff --git a/chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc b/chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc index 2b0afcbf377..2ff6b89c7e1 100644 --- a/chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc +++ b/chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc @@ -263,18 +263,22 @@ void RenderWidgetHostInputEventRouter::RouteMouseWheelEvent( RenderWidgetHostViewBase* root_view, blink::WebMouseWheelEvent* event, const ui::LatencyInfo& latency) { + RenderWidgetHostViewBase* target = nullptr; + gfx::Point transformed_point; + if (root_view->IsMouseLocked()) { - RenderWidgetHostImpl::From(root_view->GetRenderWidgetHost()) - ->delegate() - ->GetMouseLockWidget() - ->GetView() - ->ProcessMouseEvent(*event, latency); - return; + target = RenderWidgetHostImpl::From(root_view->GetRenderWidgetHost()) + ->delegate() + ->GetMouseLockWidget() + ->GetView(); + if (!root_view->TransformPointToCoordSpaceForView( + gfx::Point(event->x, event->y), target, &transformed_point)) + return; + } else { + target = FindEventTarget(root_view, gfx::Point(event->x, event->y), + &transformed_point); } - gfx::Point transformed_point; - RenderWidgetHostViewBase* target = FindEventTarget( - root_view, gfx::Point(event->x, event->y), &transformed_point); if (!target) return; diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm index 9ce93d256d4..b7f8bad5ef1 100644 --- a/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm @@ -568,7 +568,8 @@ RenderWidgetHostImpl* RenderWidgetHostViewMac::GetActiveWidget() { const TextInputManager::CompositionRangeInfo* RenderWidgetHostViewMac::GetCompositionRangeInfo() { - return text_input_manager_->GetCompositionRangeInfo(); + return GetTextInputManager() ? text_input_manager_->GetCompositionRangeInfo() + : nullptr; } const TextInputManager::TextSelection* diff --git a/chromium/content/browser/security_exploit_browsertest.cc b/chromium/content/browser/security_exploit_browsertest.cc index 3d61efb0e97..780d8223741 100644 --- a/chromium/content/browser/security_exploit_browsertest.cc +++ b/chromium/content/browser/security_exploit_browsertest.cc @@ -421,7 +421,7 @@ void OnHttpHeaderReceived(const std::string& header, int child_process_id, content::ResourceContext* resource_context, OnHeaderProcessedCallback callback) { - callback.Run(false, content::bad_message::RDH_ILLEGAL_ORIGIN); + callback.Run(HeaderInterceptorResult::KILL); } // Renderer processes should not be able to spoof Origin HTTP headers. diff --git a/chromium/content/browser/service_worker/service_worker_browsertest.cc b/chromium/content/browser/service_worker/service_worker_browsertest.cc index 9551a4878cd..6915c118ad2 100644 --- a/chromium/content/browser/service_worker/service_worker_browsertest.cc +++ b/chromium/content/browser/service_worker/service_worker_browsertest.cc @@ -1499,7 +1499,7 @@ class ServiceWorkerNavigationPreloadTest : public ServiceWorkerBrowserTest { content::ResourceContext* resource_context, OnHeaderProcessedCallback callback) { DCHECK_EQ(kNavigationPreloadHeaderName, header); - callback.Run(false, 0); + callback.Run(HeaderInterceptorResult::KILL); } void SetupForNavigationPreloadTest(const GURL& scope, diff --git a/chromium/content/common/drag_traits.h b/chromium/content/common/drag_traits.h index bf20e175fa0..16ea9b1e8fa 100644 --- a/chromium/content/common/drag_traits.h +++ b/chromium/content/common/drag_traits.h @@ -35,6 +35,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::DropData) IPC_STRUCT_TRAITS_MEMBER(html) IPC_STRUCT_TRAITS_MEMBER(html_base_url) IPC_STRUCT_TRAITS_MEMBER(file_contents) + IPC_STRUCT_TRAITS_MEMBER(file_contents_source_url) IPC_STRUCT_TRAITS_MEMBER(file_contents_filename_extension) IPC_STRUCT_TRAITS_MEMBER(file_contents_content_disposition) IPC_STRUCT_TRAITS_MEMBER(custom_data) diff --git a/chromium/content/common/gpu_host_messages.h b/chromium/content/common/gpu_host_messages.h index 6e76f92761f..01bf3d7f29d 100644 --- a/chromium/content/common/gpu_host_messages.h +++ b/chromium/content/common/gpu_host_messages.h @@ -45,6 +45,14 @@ IPC_STRUCT_BEGIN(GpuMsg_CreateGpuMemoryBuffer_Params) IPC_STRUCT_MEMBER(gpu::SurfaceHandle, surface_handle) IPC_STRUCT_END() +IPC_STRUCT_TRAITS_BEGIN(content::EstablishChannelParams) + IPC_STRUCT_TRAITS_MEMBER(client_id) + IPC_STRUCT_TRAITS_MEMBER(client_tracing_id) + IPC_STRUCT_TRAITS_MEMBER(preempts) + IPC_STRUCT_TRAITS_MEMBER(allow_view_command_buffers) + IPC_STRUCT_TRAITS_MEMBER(allow_real_time_streams) +IPC_STRUCT_TRAITS_END() + IPC_STRUCT_TRAITS_BEGIN(gpu::GpuPreferences) IPC_STRUCT_TRAITS_MEMBER(single_process) IPC_STRUCT_TRAITS_MEMBER(in_process_gpu) @@ -92,6 +100,15 @@ IPC_STRUCT_TRAITS_END() // Tells the GPU process to shutdown itself. IPC_MESSAGE_CONTROL0(GpuMsg_Finalize) +// Tells the GPU process to create a new channel for communication with a +// given client. The channel name is returned in a +// GpuHostMsg_ChannelEstablished message. The client ID is passed so +// that the GPU process reuses an existing channel to that process if it exists. +// This ID is a unique opaque identifier generated by the browser process. +// The client_tracing_id is a unique ID used for the purposes of tracing. +IPC_MESSAGE_CONTROL1(GpuMsg_EstablishChannel, + content::EstablishChannelParams /* params */) + // Tells the GPU process to close the channel identified by |client_id|. // If no channel can be identified, do nothing. IPC_MESSAGE_CONTROL1(GpuMsg_CloseChannel, int32_t /* client_id */) @@ -145,6 +162,10 @@ IPC_MESSAGE_CONTROL3(GpuHostMsg_Initialized, ::gpu::GPUInfo /* gpu_info */, ::gpu::GpuFeatureInfo /* gpu_feature_info */) +// Response from GPU to a GpuHostMsg_EstablishChannel message. +IPC_MESSAGE_CONTROL1(GpuHostMsg_ChannelEstablished, + IPC::ChannelHandle /* channel_handle */) + // Message to the GPU that a shader was loaded from disk. IPC_MESSAGE_CONTROL1(GpuMsg_LoadedShader, std::string /* encoded shader */) diff --git a/chromium/content/common/sandbox_win.cc b/chromium/content/common/sandbox_win.cc index 789a7a882d4..1b139b06f59 100644 --- a/chromium/content/common/sandbox_win.cc +++ b/chromium/content/common/sandbox_win.cc @@ -814,10 +814,12 @@ sandbox::ResultCode StartSandboxedProcess( } } +#if !defined(OFFICIAL_BUILD) // If stdout/stderr point to a Windows console, these calls will // have no effect. These calls can fail with SBOX_ERROR_BAD_PARAMS. policy->SetStdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE)); policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE)); +#endif if (!delegate->PreSpawnTarget(policy.get())) return sandbox::SBOX_ERROR_DELEGATE_PRE_SPAWN; diff --git a/chromium/content/gpu/gpu_child_thread.cc b/chromium/content/gpu/gpu_child_thread.cc index da3646ab674..a96ab43794e 100644 --- a/chromium/content/gpu/gpu_child_thread.cc +++ b/chromium/content/gpu/gpu_child_thread.cc @@ -269,6 +269,7 @@ bool GpuChildThread::OnMessageReceived(const IPC::Message& msg) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(GpuChildThread, msg) + IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel) IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel) IPC_MESSAGE_HANDLER(GpuMsg_DestroyGpuMemoryBuffer, OnDestroyGpuMemoryBuffer) IPC_MESSAGE_HANDLER(GpuMsg_LoadedShader, OnLoadedShader) @@ -455,6 +456,17 @@ void GpuChildThread::OnGpuSwitched() { ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched(); } +void GpuChildThread::OnEstablishChannel(const EstablishChannelParams& params) { + if (!gpu_channel_manager()) + return; + + IPC::ChannelHandle channel_handle = gpu_channel_manager()->EstablishChannel( + params.client_id, params.client_tracing_id, params.preempts, + params.allow_view_command_buffers, params.allow_real_time_streams); + gpu_service_->media_gpu_channel_manager()->AddChannel(params.client_id); + Send(new GpuHostMsg_ChannelEstablished(channel_handle)); +} + void GpuChildThread::OnCloseChannel(int32_t client_id) { if (gpu_channel_manager()) gpu_channel_manager()->RemoveChannel(client_id); diff --git a/chromium/content/gpu/gpu_child_thread.h b/chromium/content/gpu/gpu_child_thread.h index f44ce993d88..db030ecf1a1 100644 --- a/chromium/content/gpu/gpu_child_thread.h +++ b/chromium/content/gpu/gpu_child_thread.h @@ -46,6 +46,7 @@ class TargetServices; namespace content { class GpuServiceFactory; +struct EstablishChannelParams; // The main thread of the GPU child process. There will only ever be one of // these per process. It does process initialization and shutdown. It forwards @@ -122,6 +123,7 @@ class GpuChildThread : public ChildThreadImpl, #endif void OnGpuSwitched(); + void OnEstablishChannel(const EstablishChannelParams& params); void OnCloseChannel(int32_t client_id); void OnLoadedShader(const std::string& shader); void OnDestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, diff --git a/chromium/content/public/browser/resource_dispatcher_host.h b/chromium/content/public/browser/resource_dispatcher_host.h index a3761fbd0ef..540fa6defce 100644 --- a/chromium/content/public/browser/resource_dispatcher_host.h +++ b/chromium/content/public/browser/resource_dispatcher_host.h @@ -23,11 +23,25 @@ class ResourceContext; class ResourceDispatcherHostDelegate; class RenderFrameHost; +// This value is returned by header interceptors below, to determine if a +// request should proceed based on the values of HTTP headers. +enum class HeaderInterceptorResult { + // Allow the request to proceed with the given headers. + CONTINUE, + + // Force the request to fail, since the headers were not supported values. + FAIL, + + // Force the request to fail and kill the renderer process, since it attempted + // to use an illegal header value that could pose a security risk. + KILL, +}; + // This callback is invoked when the interceptor finishes processing the // header. -// Parameter 1 is a bool indicating success or failure. -// Parameter 2 contains the error code in case of failure, else 0. -typedef base::Callback<void(bool, int)> OnHeaderProcessedCallback; +// Parameter 1 indicates whether to continue the request, fail it, or kill the +// renderer process (and fail it). +typedef base::Callback<void(HeaderInterceptorResult)> OnHeaderProcessedCallback; // This callback is registered by interceptors who are interested in being // notified of certain HTTP headers in outgoing requests. For e.g. Origin. diff --git a/chromium/content/public/common/common_param_traits_macros.h b/chromium/content/public/common/common_param_traits_macros.h index c1b31a8dc10..95651f708c4 100644 --- a/chromium/content/public/common/common_param_traits_macros.h +++ b/chromium/content/public/common/common_param_traits_macros.h @@ -254,6 +254,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::WebPreferences) IPC_STRUCT_TRAITS_MEMBER(enable_instant_source_buffer_gc) IPC_STRUCT_TRAITS_MEMBER(presentation_receiver) IPC_STRUCT_TRAITS_MEMBER(media_controls_enabled) + IPC_STRUCT_TRAITS_MEMBER(do_not_update_selection_on_mutating_selection_range) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(blink::mojom::WindowFeatures) diff --git a/chromium/content/public/common/web_preferences.cc b/chromium/content/public/common/web_preferences.cc index 56093d39743..e67991bd769 100644 --- a/chromium/content/public/common/web_preferences.cc +++ b/chromium/content/public/common/web_preferences.cc @@ -230,7 +230,8 @@ WebPreferences::WebPreferences() base::TimeDelta::FromSeconds(10)), enable_instant_source_buffer_gc(false), presentation_receiver(false), - media_controls_enabled(true) { + media_controls_enabled(true), + do_not_update_selection_on_mutating_selection_range(false) { standard_font_family_map[kCommonScript] = base::ASCIIToUTF16("Times New Roman"); fixed_font_family_map[kCommonScript] = base::ASCIIToUTF16("Courier New"); diff --git a/chromium/content/public/common/web_preferences.h b/chromium/content/public/common/web_preferences.h index 8526cf768c6..07985ab00ea 100644 --- a/chromium/content/public/common/web_preferences.h +++ b/chromium/content/public/common/web_preferences.h @@ -290,6 +290,12 @@ struct CONTENT_EXPORT WebPreferences { // If disabled, media controls should never be used. bool media_controls_enabled; + // Whether we want to disable updating selection on mutating selection range. + // This is to work around Samsung's email app issue. See + // https://crbug.com/699943 for details. + // TODO(changwan): remove this once we no longer support Android N. + bool do_not_update_selection_on_mutating_selection_range; + // We try to keep the default values the same as the default values in // chrome, except for the cases where it would require lots of extra work for // the embedder to use the same default value. diff --git a/chromium/content/renderer/media/webmediaplayer_ms.cc b/chromium/content/renderer/media/webmediaplayer_ms.cc index e51b5c5e1ed..0a01e58aeff 100644 --- a/chromium/content/renderer/media/webmediaplayer_ms.cc +++ b/chromium/content/renderer/media/webmediaplayer_ms.cc @@ -577,6 +577,8 @@ void WebMediaPlayerMS::OnBecamePersistentVideo(bool value) { bool WebMediaPlayerMS::copyVideoTextureToPlatformTexture( gpu::gles2::GLES2Interface* gl, unsigned int texture, + unsigned int internal_format, + unsigned int type, bool premultiply_alpha, bool flip_y) { TRACE_EVENT0("media", "WebMediaPlayerMS:copyVideoTextureToPlatformTexture"); @@ -597,7 +599,8 @@ bool WebMediaPlayerMS::copyVideoTextureToPlatformTexture( context_3d = media::Context3D(provider->ContextGL(), provider->GrContext()); DCHECK(context_3d.gl); return video_renderer_.CopyVideoFrameTexturesToGLTexture( - context_3d, gl, video_frame.get(), texture, premultiply_alpha, flip_y); + context_3d, gl, video_frame.get(), texture, internal_format, type, + premultiply_alpha, flip_y); } bool WebMediaPlayerMS::texImageImpl(TexImageFunctionID functionID, diff --git a/chromium/content/renderer/media/webmediaplayer_ms.h b/chromium/content/renderer/media/webmediaplayer_ms.h index a7724c14bc9..2127a46733a 100644 --- a/chromium/content/renderer/media/webmediaplayer_ms.h +++ b/chromium/content/renderer/media/webmediaplayer_ms.h @@ -155,6 +155,8 @@ class CONTENT_EXPORT WebMediaPlayerMS bool copyVideoTextureToPlatformTexture(gpu::gles2::GLES2Interface* gl, unsigned int texture, + unsigned int internal_format, + unsigned int type, bool premultiply_alpha, bool flip_y) override; diff --git a/chromium/content/renderer/media_recorder/video_track_recorder.cc b/chromium/content/renderer/media_recorder/video_track_recorder.cc index e53129e4dc5..6fc99336398 100644 --- a/chromium/content/renderer/media_recorder/video_track_recorder.cc +++ b/chromium/content/renderer/media_recorder/video_track_recorder.cc @@ -410,6 +410,7 @@ class VEAEncoder final : public VideoTrackRecorder::Encoder, public: VEAEncoder( const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, + const VideoTrackRecorder::OnErrorCB& on_error_callback, int32_t bits_per_second, media::VideoCodecProfile codec, const gfx::Size& size); @@ -468,6 +469,9 @@ class VEAEncoder final : public VideoTrackRecorder::Encoder, // Frames and corresponding timestamps in encode as FIFO. std::queue<VideoParamsAndTimestamp> frames_in_encode_; + + // This callback can be exercised on any thread. + const VideoTrackRecorder::OnErrorCB on_error_callback_; }; // Class encapsulating all libvpx interactions for VP8/VP9 encoding. @@ -557,6 +561,7 @@ class H264Encoder final : public VideoTrackRecorder::Encoder { VEAEncoder::VEAEncoder( const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, + const VideoTrackRecorder::OnErrorCB& on_error_callback, int32_t bits_per_second, media::VideoCodecProfile codec, const gfx::Size& size) @@ -566,7 +571,8 @@ VEAEncoder::VEAEncoder( RenderThreadImpl::current()->GetGpuFactories()->GetTaskRunner()), gpu_factories_(RenderThreadImpl::current()->GetGpuFactories()), codec_(codec), - error_notified_(false) { + error_notified_(false), + on_error_callback_(on_error_callback) { DCHECK(gpu_factories_); DCHECK_GE(size.width(), kVEAEncoderMinResolutionWidth); DCHECK_GE(size.height(), kVEAEncoderMinResolutionHeight); @@ -639,8 +645,7 @@ void VEAEncoder::BitstreamBufferReady(int32_t bitstream_buffer_id, void VEAEncoder::NotifyError(media::VideoEncodeAccelerator::Error error) { DVLOG(3) << __func__; DCHECK(encoding_task_runner_->BelongsToCurrentThread()); - - // TODO(emircan): Notify the owner via a callback. + on_error_callback_.Run(); error_notified_ = true; } @@ -1156,7 +1161,10 @@ VideoTrackRecorder::VideoTrackRecorder( // InitializeEncoder() will be called on Render Main thread. MediaStreamVideoSink::ConnectToTrack( - track_, media::BindToCurrentLoop(initialize_encoder_callback_), false); + track_, + media::BindToCurrentLoop(base::Bind(initialize_encoder_callback_, + true /* allow_vea_encoder */)), + false); } VideoTrackRecorder::~VideoTrackRecorder() { @@ -1188,7 +1196,8 @@ void VideoTrackRecorder::OnVideoFrameForTesting( if (!encoder_) { DCHECK(!initialize_encoder_callback_.is_null()); - initialize_encoder_callback_.Run(frame, timestamp); + initialize_encoder_callback_.Run(true /* allow_vea_encoder */, frame, + timestamp); } encoder_->StartFrameEncode(frame, timestamp); @@ -1198,6 +1207,7 @@ void VideoTrackRecorder::InitializeEncoder( CodecId codec, const OnEncodedVideoCB& on_encoded_video_callback, int32_t bits_per_second, + bool allow_vea_encoder, const scoped_refptr<media::VideoFrame>& frame, base::TimeTicks capture_time) { DVLOG(3) << __func__ << frame->visible_rect().size().ToString(); @@ -1208,11 +1218,15 @@ void VideoTrackRecorder::InitializeEncoder( const gfx::Size& input_size = frame->visible_rect().size(); const auto& vea_supported_profile = GetCodecEnumerator()->CodecIdToVEAProfile(codec); - if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN && + if (allow_vea_encoder && + vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN && input_size.width() >= kVEAEncoderMinResolutionWidth && input_size.height() >= kVEAEncoderMinResolutionHeight) { - encoder_ = new VEAEncoder(on_encoded_video_callback, bits_per_second, - vea_supported_profile, input_size); + encoder_ = new VEAEncoder( + on_encoded_video_callback, + media::BindToCurrentLoop(base::Bind(&VideoTrackRecorder::OnError, + weak_ptr_factory_.GetWeakPtr())), + bits_per_second, vea_supported_profile, input_size); } else { switch (codec) { #if BUILDFLAG(RTC_USE_H264) @@ -1241,4 +1255,19 @@ void VideoTrackRecorder::InitializeEncoder( false); } +void VideoTrackRecorder::OnError() { + DVLOG(3) << __func__; + DCHECK(main_render_thread_checker_.CalledOnValidThread()); + + // InitializeEncoder() will be called to reinitialize encoder on Render Main + // thread. + MediaStreamVideoSink::DisconnectFromTrack(); + encoder_ = nullptr; + MediaStreamVideoSink::ConnectToTrack( + track_, + media::BindToCurrentLoop(base::Bind(initialize_encoder_callback_, + false /*allow_vea_encoder*/)), + false); +} + } // namespace content diff --git a/chromium/content/renderer/media_recorder/video_track_recorder.h b/chromium/content/renderer/media_recorder/video_track_recorder.h index 895523d696e..667cb237b82 100644 --- a/chromium/content/renderer/media_recorder/video_track_recorder.h +++ b/chromium/content/renderer/media_recorder/video_track_recorder.h @@ -53,6 +53,7 @@ class CONTENT_EXPORT VideoTrackRecorder std::unique_ptr<std::string> encoded_data, base::TimeTicks capture_timestamp, bool is_key_frame)>; + using OnErrorCB = base::Closure; static CodecId GetPreferredCodecId(); @@ -73,8 +74,10 @@ class CONTENT_EXPORT VideoTrackRecorder void InitializeEncoder(CodecId codec, const OnEncodedVideoCB& on_encoded_video_callback, int32_t bits_per_second, + bool allow_vea_encoder, const scoped_refptr<media::VideoFrame>& frame, base::TimeTicks capture_time); + void OnError(); // Used to check that we are destroyed on the same thread we were created. base::ThreadChecker main_render_thread_checker_; @@ -85,7 +88,8 @@ class CONTENT_EXPORT VideoTrackRecorder // Inner class to encode using whichever codec is configured. scoped_refptr<Encoder> encoder_; - base::Callback<void(const scoped_refptr<media::VideoFrame>& frame, + base::Callback<void(bool allow_vea_encoder, + const scoped_refptr<media::VideoFrame>& frame, base::TimeTicks capture_time)> initialize_encoder_callback_; diff --git a/chromium/content/renderer/media_recorder/video_track_recorder_unittest.cc b/chromium/content/renderer/media_recorder/video_track_recorder_unittest.cc index 093d2cf0045..1f901a6ca8c 100644 --- a/chromium/content/renderer/media_recorder/video_track_recorder_unittest.cc +++ b/chromium/content/renderer/media_recorder/video_track_recorder_unittest.cc @@ -112,6 +112,12 @@ class VideoTrackRecorderTest video_track_recorder_->OnVideoFrameForTesting(frame, capture_time); } + void OnError() { video_track_recorder_->OnError(); } + + bool HasEncoderInstance() { + return video_track_recorder_->encoder_.get() != nullptr; + } + // A ChildProcess and a MessageLoopForUI are both needed to fool the Tracks // and Sources below into believing they are on the right threads. const base::MessageLoopForUI message_loop_; @@ -211,6 +217,31 @@ TEST_P(VideoTrackRecorderTest, EncodeFrameWithPaddedCodedSize) { Mock::VerifyAndClearExpectations(this); } +// Inserts an OnError() call between sent frames. +TEST_P(VideoTrackRecorderTest, HandlesOnError) { + const gfx::Size& frame_size = kTrackRecorderTestSize[0]; + const scoped_refptr<VideoFrame> video_frame = + VideoFrame::CreateBlackFrame(frame_size); + + InSequence s; + EXPECT_CALL(*this, DoOnEncodedVideo(_, _, _, true)).Times(1); + Encode(video_frame, base::TimeTicks::Now()); + + EXPECT_TRUE(HasEncoderInstance()); + OnError(); + EXPECT_FALSE(HasEncoderInstance()); + + base::RunLoop run_loop; + base::Closure quit_closure = run_loop.QuitClosure(); + EXPECT_CALL(*this, DoOnEncodedVideo(_, _, _, true)) + .Times(1) + .WillOnce(RunClosure(quit_closure)); + Encode(video_frame, base::TimeTicks::Now()); + run_loop.Run(); + + Mock::VerifyAndClearExpectations(this); +} + INSTANTIATE_TEST_CASE_P(, VideoTrackRecorderTest, ::testing::Combine(ValuesIn(kTrackRecorderTestCodec), diff --git a/chromium/content/renderer/render_view_impl.cc b/chromium/content/renderer/render_view_impl.cc index e69e97a033c..c59e97853d4 100644 --- a/chromium/content/renderer/render_view_impl.cc +++ b/chromium/content/renderer/render_view_impl.cc @@ -1077,6 +1077,8 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs, prefs.video_fullscreen_detection_enabled); settings->setEmbeddedMediaExperienceEnabled( prefs.embedded_media_experience_enabled); + settings->setDoNotUpdateSelectionOnMutatingSelectionRange( + prefs.do_not_update_selection_on_mutating_selection_range); #else // defined(OS_ANDROID) settings->setCrossOriginMediaPlaybackRequiresUserGesture( prefs.cross_origin_media_playback_requires_user_gesture); diff --git a/chromium/content/renderer/render_widget.cc b/chromium/content/renderer/render_widget.cc index 6a4442fa9cb..b07734efdcc 100644 --- a/chromium/content/renderer/render_widget.cc +++ b/chromium/content/renderer/render_widget.cc @@ -941,6 +941,7 @@ void RenderWidget::RequestScheduleAnimation() { void RenderWidget::UpdateVisualState() { GetWebWidget()->updateAllLifecyclePhases(); + GetWebWidget()->setSuppressFrameRequestsWorkaroundFor704763Only(false); if (time_to_first_active_paint_recorded_) return; @@ -958,6 +959,8 @@ void RenderWidget::UpdateVisualState() { void RenderWidget::WillBeginCompositorFrame() { TRACE_EVENT0("gpu", "RenderWidget::willBeginCompositorFrame"); + GetWebWidget()->setSuppressFrameRequestsWorkaroundFor704763Only(true); + // The UpdateTextInputState can result in further layout and possibly // enable GPU acceleration so they need to be called before any painting // is done. |
