Commit 2537320c authored by Joel Einbinder's avatar Joel Einbinder Committed by Commit Bot

DevTools: Allow emulating page focus

Adds an option "emulate page focus" that stops blur listeners from
firing on the page. Useful for debugging focus issues.

Change-Id: I87086715d87514738a68b5b38f4df31693b97546
Reviewed-on: https://chromium-review.googlesource.com/1119257
Commit-Queue: Joel Einbinder <einbinder@chromium.org>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarAndrey Lushnikov <lushnikov@chromium.org>
Cr-Commit-Position: refs/heads/master@{#590489}
parent c120ca1d
Tests that focus emulation works.
document.hasFocus(): false
Emulating page focus
document.hasFocus(): true
Disabling focus emulation
document.hasFocus(): false
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(async function() {
TestRunner.addResult(`Tests that focus emulation works.\n`);
await dumpPageFocus();
TestRunner.addResult('\nEmulating page focus');
Common.settings.moduleSetting('emulatePageFocus').set(true);
await dumpPageFocus();
TestRunner.addResult('\nDisabling focus emulation');
Common.settings.moduleSetting('emulatePageFocus').set(false);
await dumpPageFocus();
async function dumpPageFocus() {
const pageHasFocus = await TestRunner.evaluateInPagePromise('document.hasFocus()');
TestRunner.addResult(`document.hasFocus(): ${pageHasFocus}`);
}
TestRunner.completeTest();
})();
...@@ -2461,6 +2461,12 @@ domain Emulation ...@@ -2461,6 +2461,12 @@ domain Emulation
# Requests that page scale factor is reset to initial values. # Requests that page scale factor is reset to initial values.
experimental command resetPageScaleFactor experimental command resetPageScaleFactor
# Enables or disables simulating a focused and active page.
experimental command setFocusEmulationEnabled
parameters
# Whether to enable to disable focus emulation.
boolean enabled
# Enables CPU throttling to emulate slow CPUs. # Enables CPU throttling to emulate slow CPUs.
experimental command setCPUThrottlingRate experimental command setCPUThrottlingRate
parameters parameters
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/inspector/dev_tools_emulator.h" #include "third_party/blink/renderer/core/inspector/dev_tools_emulator.h"
#include "third_party/blink/renderer/core/inspector/protocol/DOM.h" #include "third_party/blink/renderer/core/inspector/protocol/DOM.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
#include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/geometry/double_rect.h" #include "third_party/blink/renderer/platform/geometry/double_rect.h"
#include "third_party/blink/renderer/platform/graphics/color.h" #include "third_party/blink/renderer/platform/graphics/color.h"
...@@ -48,7 +49,8 @@ InspectorEmulationAgent::InspectorEmulationAgent( ...@@ -48,7 +49,8 @@ InspectorEmulationAgent::InspectorEmulationAgent(
virtual_time_offset_(&agent_state_, /*default_value=*/0.0), virtual_time_offset_(&agent_state_, /*default_value=*/0.0),
virtual_time_policy_(&agent_state_, /*default_value=*/WTF::String()), virtual_time_policy_(&agent_state_, /*default_value=*/WTF::String()),
virtual_time_task_starvation_count_(&agent_state_, /*default_value=*/0), virtual_time_task_starvation_count_(&agent_state_, /*default_value=*/0),
wait_for_navigation_(&agent_state_, /*default_value=*/false) {} wait_for_navigation_(&agent_state_, /*default_value=*/false),
emulate_focus_(&agent_state_, /*default_value=*/false) {}
InspectorEmulationAgent::~InspectorEmulationAgent() = default; InspectorEmulationAgent::~InspectorEmulationAgent() = default;
...@@ -85,6 +87,7 @@ void InspectorEmulationAgent::Restore() { ...@@ -85,6 +87,7 @@ void InspectorEmulationAgent::Restore() {
} }
} }
} }
setFocusEmulationEnabled(emulate_focus_.Get());
if (virtual_time_policy_.Get().IsNull()) if (virtual_time_policy_.Get().IsNull())
return; return;
...@@ -131,6 +134,7 @@ Response InspectorEmulationAgent::disable() { ...@@ -131,6 +134,7 @@ Response InspectorEmulationAgent::disable() {
setTouchEmulationEnabled(false, Maybe<int>()); setTouchEmulationEnabled(false, Maybe<int>());
setEmulatedMedia(String()); setEmulatedMedia(String());
setCPUThrottlingRate(1); setCPUThrottlingRate(1);
setFocusEmulationEnabled(false);
setDefaultBackgroundColorOverride(Maybe<protocol::DOM::RGBA>()); setDefaultBackgroundColorOverride(Maybe<protocol::DOM::RGBA>());
if (virtual_time_setup_) { if (virtual_time_setup_) {
DCHECK(web_local_frame_); DCHECK(web_local_frame_);
...@@ -227,6 +231,16 @@ Response InspectorEmulationAgent::setCPUThrottlingRate(double rate) { ...@@ -227,6 +231,16 @@ Response InspectorEmulationAgent::setCPUThrottlingRate(double rate) {
return response; return response;
} }
Response InspectorEmulationAgent::setFocusEmulationEnabled(bool enabled) {
Response response = AssertPage();
if (!response.isSuccess())
return response;
emulate_focus_.Set(enabled);
GetWebViewImpl()->GetPage()->GetFocusController().SetFocusEmulationEnabled(
enabled);
return response;
}
Response InspectorEmulationAgent::setVirtualTimePolicy( Response InspectorEmulationAgent::setVirtualTimePolicy(
const String& policy, const String& policy,
Maybe<double> virtual_time_budget_ms, Maybe<double> virtual_time_budget_ms,
......
...@@ -49,6 +49,7 @@ class CORE_EXPORT InspectorEmulationAgent final ...@@ -49,6 +49,7 @@ class CORE_EXPORT InspectorEmulationAgent final
protocol::Maybe<int> max_touch_points) override; protocol::Maybe<int> max_touch_points) override;
protocol::Response setEmulatedMedia(const String&) override; protocol::Response setEmulatedMedia(const String&) override;
protocol::Response setCPUThrottlingRate(double) override; protocol::Response setCPUThrottlingRate(double) override;
protocol::Response setFocusEmulationEnabled(bool) override;
protocol::Response setVirtualTimePolicy( protocol::Response setVirtualTimePolicy(
const String& policy, const String& policy,
protocol::Maybe<double> virtual_time_budget_ms, protocol::Maybe<double> virtual_time_budget_ms,
...@@ -139,6 +140,7 @@ class CORE_EXPORT InspectorEmulationAgent final ...@@ -139,6 +140,7 @@ class CORE_EXPORT InspectorEmulationAgent final
InspectorAgentState::String virtual_time_policy_; InspectorAgentState::String virtual_time_policy_;
InspectorAgentState::Integer virtual_time_task_starvation_count_; InspectorAgentState::Integer virtual_time_task_starvation_count_;
InspectorAgentState::Boolean wait_for_navigation_; InspectorAgentState::Boolean wait_for_navigation_;
InspectorAgentState::Boolean emulate_focus_;
DISALLOW_COPY_AND_ASSIGN(InspectorEmulationAgent); DISALLOW_COPY_AND_ASSIGN(InspectorEmulationAgent);
}; };
......
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
"domain": "Emulation", "domain": "Emulation",
"include": ["forceViewport", "resetViewport", "resetPageScaleFactor", "setPageScaleFactor", "setScriptExecutionDisabled", "setTouchEmulationEnabled", "include": ["forceViewport", "resetViewport", "resetPageScaleFactor", "setPageScaleFactor", "setScriptExecutionDisabled", "setTouchEmulationEnabled",
"setEmulatedMedia", "setCPUThrottlingRate", "setVirtualTimePolicy", "setNavigatorOverrides", "setDefaultBackgroundColorOverride", "setDeviceMetricsOverride", "clearDeviceMetricsOverride", "setEmulatedMedia", "setCPUThrottlingRate", "setVirtualTimePolicy", "setNavigatorOverrides", "setDefaultBackgroundColorOverride", "setDeviceMetricsOverride", "clearDeviceMetricsOverride",
"setUserAgentOverride", "setScrollbarsHidden", "setDocumentCookieDisabled"], "setUserAgentOverride", "setScrollbarsHidden", "setDocumentCookieDisabled", "setFocusEmulationEnabled"],
"include_events": ["virtualTimeBudgetExpired", "virtualTimeAdvanced", "virtualTimePaused"] "include_events": ["virtualTimeBudgetExpired", "virtualTimeAdvanced", "virtualTimePaused"]
}, },
{ {
......
...@@ -764,7 +764,8 @@ FocusController::FocusController(Page* page) ...@@ -764,7 +764,8 @@ FocusController::FocusController(Page* page)
: page_(page), : page_(page),
is_active_(false), is_active_(false),
is_focused_(false), is_focused_(false),
is_changing_focused_frame_(false) {} is_changing_focused_frame_(false),
is_emulating_focus_(false) {}
FocusController* FocusController::Create(Page* page) { FocusController* FocusController::Create(Page* page) {
return new FocusController(page); return new FocusController(page);
...@@ -887,18 +888,14 @@ bool FocusController::IsDocumentFocused(const Document& document) const { ...@@ -887,18 +888,14 @@ bool FocusController::IsDocumentFocused(const Document& document) const {
focused_frame_->Tree().IsDescendantOf(document.GetFrame()); focused_frame_->Tree().IsDescendantOf(document.GetFrame());
} }
void FocusController::SetFocused(bool focused) { void FocusController::FocusHasChanged() {
if (IsFocused() == focused) bool focused = IsFocused();
return; if (!focused && FocusedOrMainFrame()->IsLocalFrame())
is_focused_ = focused;
if (!is_focused_ && FocusedOrMainFrame()->IsLocalFrame())
ToLocalFrame(FocusedOrMainFrame())->GetEventHandler().StopAutoscroll(); ToLocalFrame(FocusedOrMainFrame())->GetEventHandler().StopAutoscroll();
// Do not set a focused frame when being unfocused. This might reset // Do not set a focused frame when being unfocused. This might reset
// m_isFocused to true. // m_isFocused to true.
if (!focused_frame_ && is_focused_) if (!focused_frame_ && focused)
SetFocusedFrame(page_->MainFrame()); SetFocusedFrame(page_->MainFrame());
// setFocusedFrame above might reject to update m_focusedFrame, or // setFocusedFrame above might reject to update m_focusedFrame, or
...@@ -913,6 +910,26 @@ void FocusController::SetFocused(bool focused) { ...@@ -913,6 +910,26 @@ void FocusController::SetFocused(bool focused) {
NotifyFocusChangedObservers(); NotifyFocusChangedObservers();
} }
void FocusController::SetFocused(bool focused) {
if (is_focused_ == focused)
return;
is_focused_ = focused;
if (!is_emulating_focus_)
FocusHasChanged();
}
void FocusController::SetFocusEmulationEnabled(bool emulate_focus) {
if (emulate_focus == is_emulating_focus_)
return;
bool active = IsActive();
bool focused = IsFocused();
is_emulating_focus_ = emulate_focus;
if (active != IsActive())
ActiveHasChanged();
if (focused != IsFocused())
FocusHasChanged();
}
bool FocusController::SetInitialFocus(WebFocusType type) { bool FocusController::SetInitialFocus(WebFocusType type) {
bool did_advance_focus = AdvanceFocus(type, true); bool did_advance_focus = AdvanceFocus(type, true);
...@@ -1229,12 +1246,7 @@ bool FocusController::SetFocusedElement(Element* element, ...@@ -1229,12 +1246,7 @@ bool FocusController::SetFocusedElement(Element* element,
return true; return true;
} }
void FocusController::SetActive(bool active) { void FocusController::ActiveHasChanged() {
if (is_active_ == active)
return;
is_active_ = active;
Frame* frame = FocusedOrMainFrame(); Frame* frame = FocusedOrMainFrame();
if (frame->IsLocalFrame()) { if (frame->IsLocalFrame()) {
Document* const document = Document* const document =
...@@ -1251,6 +1263,15 @@ void FocusController::SetActive(bool active) { ...@@ -1251,6 +1263,15 @@ void FocusController::SetActive(bool active) {
} }
} }
void FocusController::SetActive(bool active) {
if (is_active_ == active)
return;
is_active_ = active;
if (!is_emulating_focus_)
ActiveHasChanged();
}
static void UpdateFocusCandidateIfNeeded(WebFocusType direction, static void UpdateFocusCandidateIfNeeded(WebFocusType direction,
const FocusCandidate& current, const FocusCandidate& current,
FocusCandidate& candidate, FocusCandidate& candidate,
......
...@@ -91,10 +91,12 @@ class CORE_EXPORT FocusController final ...@@ -91,10 +91,12 @@ class CORE_EXPORT FocusController final
bool SetFocusedElement(Element*, Frame*); bool SetFocusedElement(Element*, Frame*);
void SetActive(bool); void SetActive(bool);
bool IsActive() const { return is_active_; } bool IsActive() const { return is_active_ || is_emulating_focus_; }
void SetFocused(bool); void SetFocused(bool);
bool IsFocused() const { return is_focused_; } bool IsFocused() const { return is_focused_ || is_emulating_focus_; }
void SetFocusEmulationEnabled(bool);
void RegisterFocusChangedObserver(FocusChangedObserver*); void RegisterFocusChangedObserver(FocusChangedObserver*);
...@@ -130,11 +132,15 @@ class CORE_EXPORT FocusController final ...@@ -130,11 +132,15 @@ class CORE_EXPORT FocusController final
void NotifyFocusChangedObservers() const; void NotifyFocusChangedObservers() const;
void ActiveHasChanged();
void FocusHasChanged();
Member<Page> page_; Member<Page> page_;
Member<Frame> focused_frame_; Member<Frame> focused_frame_;
bool is_active_; bool is_active_;
bool is_focused_; bool is_focused_;
bool is_changing_focused_frame_; bool is_changing_focused_frame_;
bool is_emulating_focus_;
HeapHashSet<WeakMember<FocusChangedObserver>> focus_changed_observers_; HeapHashSet<WeakMember<FocusChangedObserver>> focus_changed_observers_;
DISALLOW_COPY_AND_ASSIGN(FocusController); DISALLOW_COPY_AND_ASSIGN(FocusController);
}; };
......
...@@ -208,6 +208,9 @@ InspectorMain.BackendSettingsSync = class { ...@@ -208,6 +208,9 @@ InspectorMain.BackendSettingsSync = class {
this._adBlockEnabledSetting = Common.settings.moduleSetting('network.adBlockingEnabled'); this._adBlockEnabledSetting = Common.settings.moduleSetting('network.adBlockingEnabled');
this._adBlockEnabledSetting.addChangeListener(this._update, this); this._adBlockEnabledSetting.addChangeListener(this._update, this);
this._emulatePageFocusSetting = Common.settings.moduleSetting('emulatePageFocus');
this._emulatePageFocusSetting.addChangeListener(this._update, this);
SDK.targetManager.observeTargets(this, SDK.Target.Capability.Browser); SDK.targetManager.observeTargets(this, SDK.Target.Capability.Browser);
} }
...@@ -215,8 +218,10 @@ InspectorMain.BackendSettingsSync = class { ...@@ -215,8 +218,10 @@ InspectorMain.BackendSettingsSync = class {
* @param {!SDK.Target} target * @param {!SDK.Target} target
*/ */
_updateTarget(target) { _updateTarget(target) {
if (!target.parentTarget()) if (target.parentTarget())
return;
target.pageAgent().setAdBlockingEnabled(this._adBlockEnabledSetting.get()); target.pageAgent().setAdBlockingEnabled(this._adBlockEnabledSetting.get());
target.emulationAgent().setFocusEmulationEnabled(this._emulatePageFocusSetting.get());
} }
_updateAutoAttach() { _updateAutoAttach() {
......
...@@ -83,6 +83,26 @@ ...@@ -83,6 +83,26 @@
} }
] ]
}, },
{
"type": "setting",
"category": "DevTools",
"title": "Emulate a focused page",
"settingName": "emulatePageFocus",
"settingType": "boolean",
"storageType": "session",
"order": 2,
"defaultValue": false,
"options": [
{
"value": true,
"title": "Emulate a focused page"
},
{
"value": false,
"title": "Do not emulate a focused page"
}
]
},
{ {
"type": "setting", "type": "setting",
"category": "Appearance", "category": "Appearance",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment