Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: content/browser/devtools/protocol/emulation_handler.cc

Issue 2411793008: Adds BeginFrameControl via DevTools.
Patch Set: BFC prototype v2 with allow_latency_opts and waiting for BFOs. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/devtools/protocol/emulation_handler.h" 5 #include "content/browser/devtools/protocol/emulation_handler.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h"
10 #include "base/guid.h"
11 #include "base/memory/ptr_util.h"
9 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/trace_event/trace_event.h"
10 #include "build/build_config.h" 14 #include "build/build_config.h"
15 #include "cc/output/begin_frame_args.h"
16 #include "cc/surfaces/surface_id_allocator.h"
17 #include "cc/surfaces/surface_manager.h"
18 #include "content/browser/compositor/surface_utils.h"
11 #include "content/browser/frame_host/render_frame_host_impl.h" 19 #include "content/browser/frame_host/render_frame_host_impl.h"
12 #include "content/browser/renderer_host/render_widget_host_impl.h" 20 #include "content/browser/renderer_host/render_widget_host_impl.h"
13 #include "content/browser/web_contents/web_contents_impl.h" 21 #include "content/browser/web_contents/web_contents_impl.h"
22 #include "content/browser/web_contents/web_contents_view.h"
14 #include "content/common/view_messages.h" 23 #include "content/common/view_messages.h"
15 #include "content/public/common/url_constants.h" 24 #include "content/public/common/url_constants.h"
16 #include "device/geolocation/geolocation_service_context.h" 25 #include "device/geolocation/geolocation_service_context.h"
17 #include "device/geolocation/geoposition.h" 26 #include "device/geolocation/geoposition.h"
27 #include "ui/compositor/compositor.h"
18 28
19 namespace content { 29 namespace content {
20 namespace devtools { 30 namespace devtools {
21 namespace emulation { 31 namespace emulation {
22 32
23 using Response = DevToolsProtocolClient::Response; 33 using Response = DevToolsProtocolClient::Response;
24 using GeolocationServiceContext = device::GeolocationServiceContext; 34 using GeolocationServiceContext = device::GeolocationServiceContext;
25 using Geoposition = device::Geoposition; 35 using Geoposition = device::Geoposition;
26 36
27 namespace { 37 namespace {
(...skipping 21 matching lines...) Expand all
49 } 59 }
50 if (protocol_value == 60 if (protocol_value ==
51 set_touch_emulation_enabled::kConfigurationDesktop) { 61 set_touch_emulation_enabled::kConfigurationDesktop) {
52 result = ui::GestureProviderConfigType::GENERIC_DESKTOP; 62 result = ui::GestureProviderConfigType::GENERIC_DESKTOP;
53 } 63 }
54 return result; 64 return result;
55 } 65 }
56 66
57 } // namespace 67 } // namespace
58 68
69 class EmulatedBeginFrameSource : public cc::ExternalBeginFrameSource {
70 public:
71 explicit EmulatedBeginFrameSource(cc::ExternalBeginFrameSourceClient* client)
72 : cc::ExternalBeginFrameSource(client) {}
73 ~EmulatedBeginFrameSource() override {}
74
75 void DidFinishFrame(cc::BeginFrameObserver* obs,
76 size_t remaining_frames) override {
77 cc::ExternalBeginFrameSource::DidFinishFrame(obs, remaining_frames);
78 finished_observers_.insert(obs);
79 CheckFinished();
80 }
81
82 void AddObserver(cc::BeginFrameObserver* obs) override {
83 cc::ExternalBeginFrameSource::AddObserver(obs);
84 sorted_observers_.insert(obs);
85 }
86
87 void RemoveObserver(cc::BeginFrameObserver* obs) override {
88 cc::ExternalBeginFrameSource::RemoveObserver(obs);
89 sorted_observers_.erase(obs);
90 finished_observers_.erase(obs);
91 CheckFinished();
92 }
93
94 void SendBeginFrame(const cc::BeginFrameArgs& args) {
95 finished_observers_.clear();
96 OnBeginFrame(args);
97
98 for (cc::BeginFrameObserver* obs : sorted_observers_) {
99 // TODO(eseckler): Need sequence numbers in args to distinguish emulated
100 // args with equal timestamps.
101 if (obs->LastUsedBeginFrameArgs().frame_time != args.frame_time)
102 finished_observers_.insert(obs);
103 }
104 CheckFinished();
105 }
106
107 void WhenFinished(base::Callback<void()> callback) { callback_ = callback; }
108
109 private:
110 void CheckFinished() {
111 if (!base::STLIncludes(finished_observers_, sorted_observers_))
112 return;
113
114 if (callback_)
115 callback_.Run();
116 }
117
118 base::Callback<void()> callback_;
119 std::set<cc::BeginFrameObserver*> sorted_observers_;
120 std::set<cc::BeginFrameObserver*> finished_observers_;
121 };
122
59 EmulationHandler::EmulationHandler() 123 EmulationHandler::EmulationHandler()
60 : touch_emulation_enabled_(false), 124 : touch_emulation_enabled_(false),
61 device_emulation_enabled_(false), 125 device_emulation_enabled_(false),
62 host_(nullptr) { 126 begin_frame_source_(nullptr),
127 needs_begin_frame_(false),
128 host_(nullptr),
129 weak_factory_(this) {
63 } 130 }
64 131
65 EmulationHandler::~EmulationHandler() { 132 EmulationHandler::~EmulationHandler() {
66 } 133 }
67 134
68 void EmulationHandler::SetRenderFrameHost(RenderFrameHostImpl* host) { 135 void EmulationHandler::SetRenderFrameHost(RenderFrameHostImpl* host) {
69 if (host_ == host) 136 if (host_ == host)
70 return; 137 return;
71 138
139 DisableBeginFrameControl();
140
72 host_ = host; 141 host_ = host;
73 UpdateTouchEventEmulationState(); 142 UpdateTouchEventEmulationState();
74 UpdateDeviceEmulationState(); 143 UpdateDeviceEmulationState();
75 } 144 }
76 145
146 void EmulationHandler::SetClient(std::unique_ptr<Client> client) {
147 client_.swap(client);
148 }
149
77 void EmulationHandler::Detached() { 150 void EmulationHandler::Detached() {
78 touch_emulation_enabled_ = false; 151 touch_emulation_enabled_ = false;
79 device_emulation_enabled_ = false; 152 device_emulation_enabled_ = false;
80 UpdateTouchEventEmulationState(); 153 UpdateTouchEventEmulationState();
81 UpdateDeviceEmulationState(); 154 UpdateDeviceEmulationState();
155 DisableBeginFrameControl();
82 } 156 }
83 157
84 Response EmulationHandler::SetGeolocationOverride( 158 Response EmulationHandler::SetGeolocationOverride(
85 double* latitude, double* longitude, double* accuracy) { 159 double* latitude, double* longitude, double* accuracy) {
86 if (!GetWebContents()) 160 if (!GetWebContents())
87 return Response::InternalError("Could not connect to view"); 161 return Response::InternalError("Could not connect to view");
88 162
89 GeolocationServiceContext* geolocation_context = 163 GeolocationServiceContext* geolocation_context =
90 GetWebContents()->GetGeolocationServiceContext(); 164 GetWebContents()->GetGeolocationServiceContext();
91 std::unique_ptr<Geoposition> geoposition(new Geoposition()); 165 std::unique_ptr<Geoposition> geoposition(new Geoposition());
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 Response EmulationHandler::SetCPUThrottlingRate(double rate) { 357 Response EmulationHandler::SetCPUThrottlingRate(double rate) {
284 return Response::FallThrough(); 358 return Response::FallThrough();
285 } 359 }
286 360
287 Response EmulationHandler::SetVirtualTimePolicy( 361 Response EmulationHandler::SetVirtualTimePolicy(
288 const std::string& policy, 362 const std::string& policy,
289 const int* budget) { 363 const int* budget) {
290 return Response::FallThrough(); 364 return Response::FallThrough();
291 } 365 }
292 366
367 #if defined(USE_AURA)
368 Response EmulationHandler::EnableBeginFrameControl() {
369 if (begin_frame_source_)
370 return Response::OK(); // already enabled.
371
372 WebContentsImpl* web_contents = GetWebContents();
373 if (!web_contents)
374 return Response::InternalError("Could not connect to view");
375
376 ui::Compositor* compositor = web_contents->GetView()->GetCompositor();
377 if (!compositor)
378 return Response::InternalError("Could not obtain Compositor for view");
379
380 TRACE_EVENT_INSTANT2("cc", "EnableBeginFrameControl",
381 TRACE_EVENT_SCOPE_THREAD, "WebContents RoutingID",
382 web_contents->GetRoutingID(), "Compositor FrameSinkId",
383 compositor->frame_sink_id().ToString());
384
385 // TODO(eseckler): Support that Display of WebContents may change (and be
386 // destroyed) while BFC is enabled.
387
388 // Replace original BeginFrameSource by our DevTools-controlled one.
389 std::unique_ptr<cc::BeginFrameSource> begin_frame_source =
390 base::MakeUnique<EmulatedBeginFrameSource>(this);
391 begin_frame_source_ =
392 static_cast<EmulatedBeginFrameSource*>(begin_frame_source.get());
393 compositor->SwapBeginFrameSource(&begin_frame_source);
394 original_begin_frame_source_.swap(begin_frame_source);
395
396 return Response::OK();
397 }
398
399 Response EmulationHandler::DisableBeginFrameControl() {
400 if (!begin_frame_source_)
401 return Response::OK(); // already disabled.
402
403 WebContentsImpl* web_contents = GetWebContents();
404 if (!web_contents)
405 return Response::InternalError("Could not connect to view");
406
407 ui::Compositor* compositor = web_contents->GetView()->GetCompositor();
408 DCHECK(compositor);
409
410 compositor->SwapBeginFrameSource(&original_begin_frame_source_);
411 original_begin_frame_source_.reset();
412 begin_frame_source_ = nullptr;
413 needs_begin_frame_ = false;
414 return Response::OK();
415 }
416
417 Response EmulationHandler::SendBeginFrame(double interval,
418 const double* frame_time,
419 const double* deadline,
420 std::string* out_frame_id) {
421 if (!begin_frame_source_)
422 return Response::ServerError("BeginFrameControl not enabled");
423
424 RenderWidgetHostImpl* widget_host =
425 host_ ? host_->GetRenderWidgetHost() : nullptr;
426 if (!widget_host)
427 return Response::ServerError("Target does not support SendBeginFrame");
428
429 ui::Compositor* compositor = GetWebContents()->GetView()->GetCompositor();
430 DCHECK(compositor);
431
432 base::TimeTicks frame_time_ticks =
433 frame_time
434 ? base::TimeTicks::Now()
435 : base::TimeTicks() + base::TimeDelta::FromMicroseconds(*frame_time);
436 base::TimeDelta interval_delta = base::TimeDelta::FromMicroseconds(interval);
437 base::TimeTicks deadline_ticks =
438 deadline
439 ? (base::TimeTicks() + base::TimeDelta::FromMicroseconds(*deadline))
440 : (frame_time_ticks + interval_delta);
441 auto args = cc::BeginFrameArgs::Create(
442 BEGINFRAME_FROM_HERE, frame_time_ticks, deadline_ticks, interval_delta,
443 cc::BeginFrameArgs::NORMAL);
444
445 // TODO(eseckler): Expose via DevTools?
446 // Ensure that we give the renderer main thread(s) a chance to answer this
447 // BeginFrame (disables Begin(Main)Frame skipping).
448 args.allow_latency_optimizations = false;
449
450 *out_frame_id = base::GenerateGUID();
451
452 begin_frame_source_->WhenFinished(
453 base::Bind(&EmulationHandler::ClientFrameCommitted,
454 base::Unretained(this), *out_frame_id));
455 begin_frame_source_->SendBeginFrame(args);
456 return Response::OK();
457 }
458
459 #else
460 Response EmulationHandler::EnableBeginFrameControl() {
461 return Response::InternalError("Only supported on Aura.");
462 }
463
464 Response EmulationHandler::DisableBeginFrameControl() {
465 return Response::InternalError("Only supported on Aura.");
466 }
467
468 Response EmulationHandler::SendBeginFrame(double interval,
469 const double* frame_time,
470 const double* deadline,
471 std::string* out_frame_id) {
472 return Response::InternalError("Only supported on Aura.");
473 }
474 #endif
475
476 void EmulationHandler::OnNeedsBeginFrames(bool needs_begin_frames) {
477 if (needs_begin_frame_ == needs_begin_frames)
478 return;
479
480 needs_begin_frame_ = needs_begin_frames;
481 ClientSetNeedsBeginFrame(needs_begin_frame_);
482
483 // TODO(eseckler): Figure out if we need to capture needsBeginFrame updates
484 // elsewhere to avoid indicating (sole) presence of browser-level consumers.
485 }
486
487 void EmulationHandler::ClientSetNeedsBeginFrame(bool needs_begin_frame) {
488 if (!client_ || !begin_frame_source_)
489 return;
490
491 client_->SetNeedsBeginFrame(SetNeedsBeginFrameParams::Create()
492 ->set_needs_begin_frame(needs_begin_frame));
493 }
494
495 void EmulationHandler::ClientFrameCommitted(const std::string& frame_id) {
496 if (!client_ || !begin_frame_source_)
497 return;
498
499 client_->FrameCommitted(
500 FrameCommittedParams::Create()->set_frame_id(frame_id));
501 }
502
293 WebContentsImpl* EmulationHandler::GetWebContents() { 503 WebContentsImpl* EmulationHandler::GetWebContents() {
294 return host_ ? 504 return host_ ?
295 static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(host_)) : 505 static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(host_)) :
296 nullptr; 506 nullptr;
297 } 507 }
298 508
299 void EmulationHandler::UpdateTouchEventEmulationState() { 509 void EmulationHandler::UpdateTouchEventEmulationState() {
300 RenderWidgetHostImpl* widget_host = 510 RenderWidgetHostImpl* widget_host =
301 host_ ? host_->GetRenderWidgetHost() : nullptr; 511 host_ ? host_->GetRenderWidgetHost() : nullptr;
302 if (!widget_host) 512 if (!widget_host)
(...skipping 16 matching lines...) Expand all
319 widget_host->GetRoutingID(), device_emulation_params_)); 529 widget_host->GetRoutingID(), device_emulation_params_));
320 } else { 530 } else {
321 widget_host->Send(new ViewMsg_DisableDeviceEmulation( 531 widget_host->Send(new ViewMsg_DisableDeviceEmulation(
322 widget_host->GetRoutingID())); 532 widget_host->GetRoutingID()));
323 } 533 }
324 } 534 }
325 535
326 } // namespace emulation 536 } // namespace emulation
327 } // namespace devtools 537 } // namespace devtools
328 } // namespace content 538 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/devtools/protocol/emulation_handler.h ('k') | content/browser/renderer_host/render_widget_host_view_aura.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698