Commit 11805ff0 authored by Dominic Mazzoni's avatar Dominic Mazzoni Committed by Commit Bot

Free up accessibility tree resources from hidden frames.

When a frame is hidden, replace its accessibility tree with just the root,
and suppress all accessibility events in that tree while it's hidden.
By keeping the root in the tree, this allows us to propagate the change
to the browser process and free up resources there too.

The goal is that having lots of tabs open shouldn't significantly impact
your experience.

It may add a slight delay when switching to a tab.

Bug: 854411
Change-Id: I78b45e8f5772f0c9745ee59952f27f6ba3557bbc
Reviewed-on: https://chromium-review.googlesource.com/1107207
Commit-Queue: Dominic Mazzoni <dmazzoni@chromium.org>
Reviewed-by: default avatarNektarios Paisios <nektar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#569422}
parent e0a57fa4
// Copyright 2014 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.
function createBackgroundTab(url, callback) {
function createTabInNewInactiveWindow(url, callback) {
chrome.tabs.query({ active: true }, function(tabs) {
chrome.test.assertEq(1, tabs.length);
var originalActiveTab = tabs[0];
createTab(url, function(tab) {
chrome.windows.create({"url": url, "focused": false}, function(win) {
chrome.tabs.update(originalActiveTab.id, { active: true }, function() {
callback(tab);
callback(win.tabs[0]);
});
})
});
......@@ -26,7 +25,7 @@ var allTests = [
getUrlFromConfig('index.html', function(url) {
// Keep the NTP as the active tab so that we know we're requesting the
// tab by ID rather than just getting the active tab still.
createBackgroundTab(url, function(tab) {
createTabInNewInactiveWindow(url, function(tab) {
chrome.automation.getTree(tab.id, function(rootNode) {
if (rootNode.docLoaded) {
assertCorrectTab(rootNode);
......
......@@ -214,11 +214,22 @@ ScopedFreezeBlinkAXTreeSource::~ScopedFreezeBlinkAXTreeSource() {
BlinkAXTreeSource::BlinkAXTreeSource(RenderFrameImpl* render_frame,
ui::AXMode mode)
: render_frame_(render_frame), accessibility_mode_(mode), frozen_(false) {}
: render_frame_(render_frame),
accessibility_mode_(mode),
frozen_(false),
hidden_(false) {}
BlinkAXTreeSource::~BlinkAXTreeSource() {
}
void BlinkAXTreeSource::WasHidden() {
hidden_ = true;
}
void BlinkAXTreeSource::WasShown() {
hidden_ = false;
}
void BlinkAXTreeSource::Freeze() {
CHECK(!frozen_);
frozen_ = true;
......@@ -372,6 +383,9 @@ void BlinkAXTreeSource::GetChildren(
std::vector<WebAXObject>* out_children) const {
CHECK(frozen_);
if (hidden_)
return;
if ((parent.Role() == blink::kWebAXRoleStaticText ||
parent.Role() == blink::kWebAXRoleLineBreak) &&
ShouldLoadInlineTextBoxes(parent)) {
......@@ -402,6 +416,9 @@ void BlinkAXTreeSource::GetChildren(
WebAXObject BlinkAXTreeSource::GetParent(WebAXObject node) const {
CHECK(frozen_);
if (hidden_)
return WebAXObject();
// Blink returns ignored objects when walking up the parent chain,
// we have to skip those here. Also, stop when we get to the root
// element.
......@@ -415,6 +432,9 @@ WebAXObject BlinkAXTreeSource::GetParent(WebAXObject node) const {
}
bool BlinkAXTreeSource::IsValid(WebAXObject node) const {
if (hidden_ && !node.Equals(root()))
return false;
return !node.IsDetached(); // This also checks if it's null.
}
......
......@@ -42,6 +42,11 @@ class BlinkAXTreeSource
BlinkAXTreeSource(RenderFrameImpl* render_frame, ui::AXMode mode);
~BlinkAXTreeSource() override;
// If the frame is hidden, expose only the root node and skip the
// rest of the tree.
void WasHidden();
void WasShown();
// Freeze caches the document, accessibility root, and current focused
// object for fast retrieval during a batch of operations. Use
// ScopedFreezeBlinkAXTreeSource on the stack rather than calling
......@@ -130,6 +135,10 @@ class BlinkAXTreeSource
blink::WebDocument document_;
blink::WebAXObject root_;
blink::WebAXObject focus_;
// If the page is hidden, we eliminate everything other than the
// root node.
bool hidden_;
};
} // namespace content
......
......@@ -125,6 +125,9 @@ RenderAccessibilityImpl::RenderAccessibilityImpl(RenderFrameImpl* render_frame,
settings->SetInlineTextBoxAccessibilityEnabled(true);
#endif
if (render_frame_->IsHidden())
tree_source_.WasHidden();
const WebDocument& document = GetMainDocument();
if (!document.IsNull()) {
// It's possible that the webview has already loaded a webpage without
......@@ -194,8 +197,22 @@ bool RenderAccessibilityImpl::OnMessageReceived(const IPC::Message& message) {
return handled;
}
void RenderAccessibilityImpl::WasHidden() {
pending_events_.clear();
tree_source_.WasHidden();
HandleAXEvent(tree_source_.GetRoot(), ax::mojom::Event::kNone);
}
void RenderAccessibilityImpl::WasShown() {
pending_events_.clear();
tree_source_.WasShown();
HandleAXEvent(tree_source_.GetRoot(), ax::mojom::Event::kNone);
}
void RenderAccessibilityImpl::HandleWebAccessibilityEvent(
const blink::WebAXObject& obj, blink::WebAXEvent event) {
if (render_frame_->IsHidden())
return;
HandleAXEvent(obj, AXEventFromBlink(event));
}
......
......@@ -75,6 +75,8 @@ class CONTENT_EXPORT RenderAccessibilityImpl
// RenderFrameObserver implementation.
void AccessibilityModeChanged() override;
bool OnMessageReceived(const IPC::Message& message) override;
void WasHidden() override;
void WasShown() override;
// Called when an accessibility notification occurs in Blink.
void HandleWebAccessibilityEvent(const blink::WebAXObject& obj,
......
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