Commit 3475be27 authored by dtseng's avatar dtseng Committed by Commit bot

Ensure WebView notifies desktop automation on creation, destruction, and change

Currently, when a caller requests a desktop tree and then opens a new windowthe new WebViewmight have an unloaded child root web area because the tree id sent on construction may be stale by the time automation gets it. Adding a notification in WebView::RenderViewHostChanged appears to work properly.

This also allows ChromeVox to add one set of listeners on the desktop node.

TEST=With ChromeVox Next set to use automation,
- navigate within a tab
- switch to several tabs and navigate
- open new windows and navigate
Result should be that events fire properly when tabbing within the new page.

Review URL: https://codereview.chromium.org/880063002

Cr-Commit-Position: refs/heads/master@{#314017}
parent e49c5137
...@@ -1511,6 +1511,7 @@ chrome.automation.RoleType = { ...@@ -1511,6 +1511,7 @@ chrome.automation.RoleType = {
unknown: 'unknown', unknown: 'unknown',
tooltip: 'tooltip', tooltip: 'tooltip',
webArea: 'webArea', webArea: 'webArea',
webView: 'webView',
window: 'window' window: 'window'
}; };
/** /**
......
...@@ -6,6 +6,7 @@ goog.provide('cvox.ChromeVoxEditableTextBase'); ...@@ -6,6 +6,7 @@ goog.provide('cvox.ChromeVoxEditableTextBase');
goog.provide('cvox.TextChangeEvent'); goog.provide('cvox.TextChangeEvent');
goog.provide('cvox.TypingEcho'); goog.provide('cvox.TypingEcho');
goog.require('cvox.AbstractTts');
goog.require('cvox.ChromeVox'); goog.require('cvox.ChromeVox');
goog.require('cvox.TtsInterface'); goog.require('cvox.TtsInterface');
goog.require('goog.i18n.MessageFormat'); goog.require('goog.i18n.MessageFormat');
......
...@@ -88,8 +88,12 @@ AutomationUtil.findNextSubtree = function(cur, dir) { ...@@ -88,8 +88,12 @@ AutomationUtil.findNextSubtree = function(cur, dir) {
while (cur) { while (cur) {
var next = dir == Dir.BACKWARD ? var next = dir == Dir.BACKWARD ?
cur.previousSibling : cur.nextSibling; cur.previousSibling : cur.nextSibling;
if (!AutomationUtil.isInSameTree(cur, next))
return null;
if (next) if (next)
return next; return next;
if (!AutomationUtil.isInSameTree(cur, cur.parent))
return null;
cur = cur.parent; cur = cur.parent;
} }
}; };
...@@ -164,6 +168,10 @@ AutomationUtil.getAncestors = function(node) { ...@@ -164,6 +168,10 @@ AutomationUtil.getAncestors = function(node) {
var candidate = node; var candidate = node;
while (candidate) { while (candidate) {
ret.push(candidate); ret.push(candidate);
if (!AutomationUtil.isInSameTree(candidate, candidate.parent))
break;
candidate = candidate.parent; candidate = candidate.parent;
} }
return ret.reverse(); return ret.reverse();
...@@ -226,4 +234,17 @@ AutomationUtil.getDirection = function(nodeA, nodeB) { ...@@ -226,4 +234,17 @@ AutomationUtil.getDirection = function(nodeA, nodeB) {
return divA.indexInParent <= divB.indexInParent ? Dir.FORWARD : Dir.BACKWARD; return divA.indexInParent <= divB.indexInParent ? Dir.FORWARD : Dir.BACKWARD;
}; };
/**
* Determines whether the two given nodes come from the same tree source.
* @param {AutomationNode} a
* @param {AutomationNode} b
* @return {boolean}
*/
AutomationUtil.isInSameTree = function(a, b) {
if (!a || !b)
return true;
return a.root === b.root;
};
}); // goog.scope }); // goog.scope
...@@ -16,7 +16,6 @@ goog.require('Output'); ...@@ -16,7 +16,6 @@ goog.require('Output');
goog.require('Output.EventType'); goog.require('Output.EventType');
goog.require('cursors.Cursor'); goog.require('cursors.Cursor');
goog.require('cvox.ChromeVoxEditableTextBase'); goog.require('cvox.ChromeVoxEditableTextBase');
goog.require('cvox.TabsApiHandler');
goog.scope(function() { goog.scope(function() {
var AutomationNode = chrome.automation.AutomationNode; var AutomationNode = chrome.automation.AutomationNode;
...@@ -36,14 +35,6 @@ Background = function() { ...@@ -36,14 +35,6 @@ Background = function() {
*/ */
this.whitelist_ = ['chromevox_next_test']; this.whitelist_ = ['chromevox_next_test'];
/**
* @type {cvox.TabsApiHandler}
* @private
*/
this.tabsHandler_ = new cvox.TabsApiHandler(cvox.ChromeVox.tts,
cvox.ChromeVox.braille,
cvox.ChromeVox.earcons);
/** /**
* @type {cursors.Range} * @type {cursors.Range}
* @private * @private
...@@ -82,43 +73,29 @@ Background = function() { ...@@ -82,43 +73,29 @@ Background = function() {
// Register listeners for ... // Register listeners for ...
// Desktop. // Desktop.
chrome.automation.getDesktop(this.onGotTree); chrome.automation.getDesktop(this.onGotDesktop);
// Tabs.
chrome.tabs.onUpdated.addListener(this.onTabUpdated);
}; };
Background.prototype = { Background.prototype = {
/**
* Handles chrome.tabs.onUpdated.
* @param {number} tabId
* @param {Object} changeInfo
*/
onTabUpdated: function(tabId, changeInfo) {
if (changeInfo.status != 'complete')
return;
chrome.tabs.get(tabId, function(tab) {
if (!tab.url)
return;
var next = this.isWhitelisted_(tab.url);
this.toggleChromeVoxVersion({next: next, classic: !next});
}.bind(this));
},
/** /**
* Handles all setup once a new automation tree appears. * Handles all setup once a new automation tree appears.
* @param {chrome.automation.AutomationNode} root * @param {chrome.automation.AutomationNode} desktop
*/ */
onGotTree: function(root) { onGotDesktop: function(desktop) {
// Register all automation event listeners. // Register all automation event listeners.
for (var eventType in this.listeners_) for (var eventType in this.listeners_)
root.addEventListener(eventType, this.listeners_[eventType], true); desktop.addEventListener(eventType, this.listeners_[eventType], true);
if (root.attributes.docLoaded) { // The focused state gets set on the containing webView node.
this.onLoadComplete( var webView = desktop.find({role: chrome.automation.RoleType.webView,
{target: root, type: chrome.automation.EventType.loadComplete}); state: {focused: true}});
if (webView) {
var root = webView.find({role: chrome.automation.RoleType.rootWebArea});
if (root) {
this.onLoadComplete(
{target: root,
type: chrome.automation.EventType.loadComplete});
}
} }
}, },
...@@ -270,14 +247,30 @@ Background.prototype = { ...@@ -270,14 +247,30 @@ Background.prototype = {
* @param {Object} evt * @param {Object} evt
*/ */
onLoadComplete: function(evt) { onLoadComplete: function(evt) {
console.log('processing load complete!');
var next = this.isWhitelisted_(evt.target.attributes.url);
this.toggleChromeVoxVersion({next: next, classic: !next});
// Don't process nodes inside of web content if ChromeVox Next is inactive. // Don't process nodes inside of web content if ChromeVox Next is inactive.
if (evt.target.root.role != chrome.automation.RoleType.desktop && if (evt.target.root.role != chrome.automation.RoleType.desktop &&
!this.active_) !this.active_)
return; return;
var node = AutomationUtil.findNodePost(evt.target, if (this.currentRange_)
return;
var root = evt.target;
var webView = root;
while (webView && webView.role != chrome.automation.RoleType.webView)
webView = webView.parent;
if (!webView || !webView.state.focused)
return;
var node = AutomationUtil.findNodePost(root,
Dir.FORWARD, Dir.FORWARD,
AutomationPredicate.leaf); AutomationPredicate.leaf);
if (node) if (node)
this.currentRange_ = cursors.Range.fromNode(node); this.currentRange_ = cursors.Range.fromNode(node);
...@@ -362,21 +355,11 @@ Background.prototype = { ...@@ -362,21 +355,11 @@ Background.prototype = {
if (opt_options.next) { if (opt_options.next) {
if (!chrome.commands.onCommand.hasListener(this.onGotCommand)) if (!chrome.commands.onCommand.hasListener(this.onGotCommand))
chrome.commands.onCommand.addListener(this.onGotCommand); chrome.commands.onCommand.addListener(this.onGotCommand);
this.active_ = true;
if (!this.active_)
chrome.automation.getTree(this.onGotTree);
this.active_ = true;
} else { } else {
if (chrome.commands.onCommand.hasListener(this.onGotCommand)) if (chrome.commands.onCommand.hasListener(this.onGotCommand))
chrome.commands.onCommand.removeListener(this.onGotCommand); chrome.commands.onCommand.removeListener(this.onGotCommand);
if (this.active_) {
for (var eventType in this.listeners_) {
this.currentRange_.getStart().getNode().root.removeEventListener(
eventType, this.listeners_[eventType], true);
}
}
this.active_ = false; this.active_ = false;
} }
......
...@@ -97,7 +97,7 @@ TEST_F('BackgroundTest', 'InitialFeedback', function() { ...@@ -97,7 +97,7 @@ TEST_F('BackgroundTest', 'InitialFeedback', function() {
}, true); }, true);
cvox.ChromeVox.tts.expectSpeech('end', testDone, true); cvox.ChromeVox.tts.expectSpeech('end', testDone, true);
this.runWithDocument(function() {/*! this.runWithAutomation(function() {/*!
<p>start <p>start
<p>end <p>end
*/}, */},
...@@ -107,7 +107,7 @@ TEST_F('BackgroundTest', 'InitialFeedback', function() { ...@@ -107,7 +107,7 @@ TEST_F('BackgroundTest', 'InitialFeedback', function() {
/** Tests consistency of navigating forward and backward. */ /** Tests consistency of navigating forward and backward. */
TEST_F('BackgroundTest', 'ForwardBackwardNavigation', function() { TEST_F('BackgroundTest', 'ForwardBackwardNavigation', function() {
cvox.ChromeVox.tts.expectSpeech('start', null, true); cvox.ChromeVox.tts.expectSpeech('start', null, true);
this.runWithDocument(this.linksAndHeadingsDoc, function() { this.runWithAutomation(this.linksAndHeadingsDoc, function() {
var doCmd = this.doCmd.bind(this); var doCmd = this.doCmd.bind(this);
var expectAfter = var expectAfter =
cvox.ChromeVox.tts.expectSpeechAfter.bind(cvox.ChromeVox.tts); cvox.ChromeVox.tts.expectSpeechAfter.bind(cvox.ChromeVox.tts);
...@@ -138,7 +138,7 @@ TEST_F('BackgroundTest', 'ForwardBackwardNavigation', function() { ...@@ -138,7 +138,7 @@ TEST_F('BackgroundTest', 'ForwardBackwardNavigation', function() {
TEST_F('BackgroundTest', 'CaretNavigation', function() { TEST_F('BackgroundTest', 'CaretNavigation', function() {
cvox.ChromeVox.tts.expectSpeech('start', null, true); cvox.ChromeVox.tts.expectSpeech('start', null, true);
this.runWithDocument(this.linksAndHeadingsDoc, function() { this.runWithAutomation(this.linksAndHeadingsDoc, function() {
var doCmd = this.doCmd.bind(this); var doCmd = this.doCmd.bind(this);
var expectAfter = var expectAfter =
cvox.ChromeVox.tts.expectSpeechAfter.bind(cvox.ChromeVox.tts); cvox.ChromeVox.tts.expectSpeechAfter.bind(cvox.ChromeVox.tts);
...@@ -168,7 +168,7 @@ TEST_F('BackgroundTest', 'CaretNavigation', function() { ...@@ -168,7 +168,7 @@ TEST_F('BackgroundTest', 'CaretNavigation', function() {
// Flaky: http://crbug.com/451362 // Flaky: http://crbug.com/451362
TEST_F('BackgroundTest', 'DISABLED_SelectSingleBasic', function() { TEST_F('BackgroundTest', 'DISABLED_SelectSingleBasic', function() {
this.runWithDocument(this.formsDoc, function(tabId) { this.runWithAutomation(this.formsDoc, function(tabId) {
var sendDownToSelect = var sendDownToSelect =
this.sendKeyToElement.bind(this, tabId, 'Down', '#fruitSelect'); this.sendKeyToElement.bind(this, tabId, 'Down', '#fruitSelect');
var expect = cvox.ChromeVox.tts.expectSpeech.bind(cvox.ChromeVox.tts); var expect = cvox.ChromeVox.tts.expectSpeech.bind(cvox.ChromeVox.tts);
...@@ -181,7 +181,7 @@ TEST_F('BackgroundTest', 'DISABLED_SelectSingleBasic', function() { ...@@ -181,7 +181,7 @@ TEST_F('BackgroundTest', 'DISABLED_SelectSingleBasic', function() {
TEST_F('BackgroundTest', 'ContinuousRead', function() { TEST_F('BackgroundTest', 'ContinuousRead', function() {
cvox.ChromeVox.tts.expectSpeech('start', null, true); cvox.ChromeVox.tts.expectSpeech('start', null, true);
this.runWithDocument(this.linksAndHeadingsDoc, function() { this.runWithAutomation(this.linksAndHeadingsDoc, function() {
var doCmd = this.doCmd.bind(this); var doCmd = this.doCmd.bind(this);
var expect = var expect =
cvox.ChromeVox.tts.expectSpeechAfter.bind(cvox.ChromeVox.tts); cvox.ChromeVox.tts.expectSpeechAfter.bind(cvox.ChromeVox.tts);
......
...@@ -70,6 +70,7 @@ CursorsTest.prototype = { ...@@ -70,6 +70,7 @@ CursorsTest.prototype = {
range = range.move(move[0], move[1]); range = range.move(move[0], move[1]);
var expectedStart = move[2]; var expectedStart = move[2];
var expectedEnd = move[3]; var expectedEnd = move[3];
this.makeCursorAssertion(expectedStart, range.getStart()); this.makeCursorAssertion(expectedStart, range.getStart());
this.makeCursorAssertion(expectedEnd, range.getEnd()); this.makeCursorAssertion(expectedEnd, range.getEnd());
} }
...@@ -93,27 +94,25 @@ CursorsTest.prototype = { ...@@ -93,27 +94,25 @@ CursorsTest.prototype = {
* @param {string=} opt_testType Either CURSOR or RANGE. * @param {string=} opt_testType Either CURSOR or RANGE.
*/ */
runCursorMovesOnDocument: function(doc, moves, opt_testType) { runCursorMovesOnDocument: function(doc, moves, opt_testType) {
this.runWithDocument(doc, this.runWithAutomation(doc,
function() { function(root) {
chrome.automation.getTree(function(root) { var start = null;
var start = null;
// This occurs as a result of a load complete. // This occurs as a result of a load complete.
var start = AutomationUtil.findNodePost(root, var start = AutomationUtil.findNodePost(root,
FORWARD, FORWARD,
AutomationPredicate.leaf); AutomationPredicate.leaf);
var cursor = new cursors.Cursor(start, 0);
if (!opt_testType || opt_testType == this.CURSOR) {
var cursor = new cursors.Cursor(start, 0); var cursor = new cursors.Cursor(start, 0);
if (!opt_testType || opt_testType == this.CURSOR) { this.cursorMoveAndAssert(cursor, moves);
var cursor = new cursors.Cursor(start, 0); testDone();
this.cursorMoveAndAssert(cursor, moves); } else if (opt_testType == this.RANGE) {
testDone(); var range = new cursors.Range(cursor, cursor);
} else if (opt_testType == this.RANGE) { this.rangeMoveAndAssert(range, moves);
var range = new cursors.Range(cursor, cursor); testDone();
this.rangeMoveAndAssert(range, moves); }
testDone();
}
}.bind(this));
}.bind(this)); }.bind(this));
}, },
......
...@@ -13,6 +13,8 @@ goog.require('AutomationUtil.Dir'); ...@@ -13,6 +13,8 @@ goog.require('AutomationUtil.Dir');
goog.require('cursors.Cursor'); goog.require('cursors.Cursor');
goog.require('cursors.Range'); goog.require('cursors.Range');
goog.require('cursors.Unit'); goog.require('cursors.Unit');
goog.require('cvox.AbstractEarcons');
goog.require('cvox.NavBraille');
goog.require('cvox.Spannable'); goog.require('cvox.Spannable');
goog.require('cvox.ValueSelectionSpan'); goog.require('cvox.ValueSelectionSpan');
goog.require('cvox.ValueSpan'); goog.require('cvox.ValueSpan');
......
...@@ -32,7 +32,14 @@ ChromeVoxNextE2ETest.prototype = { ...@@ -32,7 +32,14 @@ ChromeVoxNextE2ETest.prototype = {
runWithAutomation: function(doc, callback) { runWithAutomation: function(doc, callback) {
this.runWithDocument(doc, function() { this.runWithDocument(doc, function() {
chrome.automation.getTree(function(root) { chrome.automation.getTree(function(root) {
callback(root); if (root.children.length == 0) {
root.addEventListener('loadComplete',
function() {
callback(root);
}.bind(this), true);
} else {
callback(root);
}
}.bind(this)); }.bind(this));
}.bind(this)); }.bind(this));
} }
......
...@@ -113,7 +113,7 @@ MockTts.prototype = { ...@@ -113,7 +113,7 @@ MockTts.prototype = {
// Process any idleUtterances. // Process any idleUtterances.
this.idleUtterances_.forEach(function(utterance) { this.idleUtterances_.forEach(function(utterance) {
this.process_(utterance, true); this.process_(utterance, true);
}); }.bind(this));
}, },
/** /**
......
...@@ -728,7 +728,7 @@ AutomationRootNodeImpl.prototype = { ...@@ -728,7 +728,7 @@ AutomationRootNodeImpl.prototype = {
// TODO(dtseng): Make into set listing all hosting node roles. // TODO(dtseng): Make into set listing all hosting node roles.
if (nodeData.role == schema.RoleType.webView) { if (nodeData.role == schema.RoleType.webView) {
if (nodeImpl.pendingChildFrame === undefined) if (nodeImpl.childTreeID !== nodeData.intAttributes.childTreeId)
nodeImpl.pendingChildFrame = true; nodeImpl.pendingChildFrame = true;
if (nodeImpl.pendingChildFrame) { if (nodeImpl.pendingChildFrame) {
......
...@@ -17,7 +17,7 @@ class ExtensionJSBrowserTest : public JavaScriptBrowserTest { ...@@ -17,7 +17,7 @@ class ExtensionJSBrowserTest : public JavaScriptBrowserTest {
public: public:
ExtensionJSBrowserTest(); ExtensionJSBrowserTest();
virtual ~ExtensionJSBrowserTest(); ~ExtensionJSBrowserTest() override;
protected: protected:
// Waits for an extension to load; returns immediately if already loaded. // Waits for an extension to load; returns immediately if already loaded.
......
...@@ -19,16 +19,16 @@ class BrowserContext; ...@@ -19,16 +19,16 @@ class BrowserContext;
class ExtensionLoadWaiterOneShot : public content::NotificationObserver { class ExtensionLoadWaiterOneShot : public content::NotificationObserver {
public: public:
ExtensionLoadWaiterOneShot(); ExtensionLoadWaiterOneShot();
virtual ~ExtensionLoadWaiterOneShot(); ~ExtensionLoadWaiterOneShot() override;
// Waits for extension with |extension_id| to load. The id should be a pointer // Waits for extension with |extension_id| to load. The id should be a pointer
// to a static char array. // to a static char array.
void WaitForExtension(const char* extension_id, const base::Closure& load_cb); void WaitForExtension(const char* extension_id, const base::Closure& load_cb);
// content::NotificationObserver overrides. // content::NotificationObserver overrides.
virtual void Observe(int type, void Observe(int type,
const content::NotificationSource& source, const content::NotificationSource& source,
const content::NotificationDetails& details) override; const content::NotificationDetails& details) override;
// Get the browser context associated with the loaded extension. Returns // Get the browser context associated with the loaded extension. Returns
// NULL if |WaitForExtension| was not previously called. // NULL if |WaitForExtension| was not previously called.
......
...@@ -78,7 +78,7 @@ void WebView::SetWebContents(content::WebContents* replacement) { ...@@ -78,7 +78,7 @@ void WebView::SetWebContents(content::WebContents* replacement) {
DCHECK(!is_embedding_fullscreen_widget_); DCHECK(!is_embedding_fullscreen_widget_);
} }
AttachWebContents(); AttachWebContents();
NotifyMaybeTextInputClientChanged(); NotifyMaybeTextInputClientAndAccessibilityChanged();
} }
void WebView::SetEmbedFullscreenWidgetMode(bool enable) { void WebView::SetEmbedFullscreenWidgetMode(bool enable) {
...@@ -266,7 +266,7 @@ gfx::Size WebView::GetPreferredSize() const { ...@@ -266,7 +266,7 @@ gfx::Size WebView::GetPreferredSize() const {
void WebView::RenderProcessExited(content::RenderProcessHost* host, void WebView::RenderProcessExited(content::RenderProcessHost* host,
base::TerminationStatus status, base::TerminationStatus status,
int exit_code) { int exit_code) {
NotifyMaybeTextInputClientChanged(); NotifyMaybeTextInputClientAndAccessibilityChanged();
} }
void WebView::RenderProcessHostDestroyed(content::RenderProcessHost* host) { void WebView::RenderProcessHostDestroyed(content::RenderProcessHost* host) {
...@@ -293,11 +293,11 @@ bool WebView::EmbedsFullscreenWidget() const { ...@@ -293,11 +293,11 @@ bool WebView::EmbedsFullscreenWidget() const {
// WebView, content::WebContentsObserver implementation: // WebView, content::WebContentsObserver implementation:
void WebView::RenderViewReady() { void WebView::RenderViewReady() {
NotifyMaybeTextInputClientChanged(); NotifyMaybeTextInputClientAndAccessibilityChanged();
} }
void WebView::RenderViewDeleted(content::RenderViewHost* render_view_host) { void WebView::RenderViewDeleted(content::RenderViewHost* render_view_host) {
NotifyMaybeTextInputClientChanged(); NotifyMaybeTextInputClientAndAccessibilityChanged();
} }
void WebView::RenderViewHostChanged(content::RenderViewHost* old_host, void WebView::RenderViewHostChanged(content::RenderViewHost* old_host,
...@@ -305,7 +305,7 @@ void WebView::RenderViewHostChanged(content::RenderViewHost* old_host, ...@@ -305,7 +305,7 @@ void WebView::RenderViewHostChanged(content::RenderViewHost* old_host,
FocusManager* const focus_manager = GetFocusManager(); FocusManager* const focus_manager = GetFocusManager();
if (focus_manager && focus_manager->GetFocusedView() == this) if (focus_manager && focus_manager->GetFocusedView() == this)
OnFocus(); OnFocus();
NotifyMaybeTextInputClientChanged(); NotifyMaybeTextInputClientAndAccessibilityChanged();
} }
void WebView::WebContentsDestroyed() { void WebView::WebContentsDestroyed() {
...@@ -313,7 +313,7 @@ void WebView::WebContentsDestroyed() { ...@@ -313,7 +313,7 @@ void WebView::WebContentsDestroyed() {
observing_render_process_host_->RemoveObserver(this); observing_render_process_host_->RemoveObserver(this);
observing_render_process_host_ = nullptr; observing_render_process_host_ = nullptr;
} }
NotifyMaybeTextInputClientChanged(); NotifyMaybeTextInputClientAndAccessibilityChanged();
} }
void WebView::DidShowFullscreenWidget(int routing_id) { void WebView::DidShowFullscreenWidget(int routing_id) {
...@@ -332,11 +332,11 @@ void WebView::DidToggleFullscreenModeForTab(bool entered_fullscreen) { ...@@ -332,11 +332,11 @@ void WebView::DidToggleFullscreenModeForTab(bool entered_fullscreen) {
} }
void WebView::DidAttachInterstitialPage() { void WebView::DidAttachInterstitialPage() {
NotifyMaybeTextInputClientChanged(); NotifyMaybeTextInputClientAndAccessibilityChanged();
} }
void WebView::DidDetachInterstitialPage() { void WebView::DidDetachInterstitialPage() {
NotifyMaybeTextInputClientChanged(); NotifyMaybeTextInputClientAndAccessibilityChanged();
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
...@@ -398,14 +398,18 @@ void WebView::ReattachForFullscreenChange(bool enter_fullscreen) { ...@@ -398,14 +398,18 @@ void WebView::ReattachForFullscreenChange(bool enter_fullscreen) {
// the same. So, do not change attachment. // the same. So, do not change attachment.
OnBoundsChanged(bounds()); OnBoundsChanged(bounds());
} }
NotifyMaybeTextInputClientChanged(); NotifyMaybeTextInputClientAndAccessibilityChanged();
} }
void WebView::NotifyMaybeTextInputClientChanged() { void WebView::NotifyMaybeTextInputClientAndAccessibilityChanged() {
// Update the TextInputClient as needed; see GetTextInputClient(). // Update the TextInputClient as needed; see GetTextInputClient().
FocusManager* const focus_manager = GetFocusManager(); FocusManager* const focus_manager = GetFocusManager();
if (focus_manager) if (focus_manager)
focus_manager->OnTextInputClientChanged(this); focus_manager->OnTextInputClientChanged(this);
#if defined(OS_CHROMEOS)
NotifyAccessibilityEvent(ui::AX_EVENT_CHILDREN_CHANGED, true);
#endif // defined OS_CHROMEOS
} }
content::WebContents* WebView::CreateWebContents( content::WebContents* WebView::CreateWebContents(
......
...@@ -149,7 +149,7 @@ class WEBVIEW_EXPORT WebView : public View, ...@@ -149,7 +149,7 @@ class WEBVIEW_EXPORT WebView : public View,
void AttachWebContents(); void AttachWebContents();
void DetachWebContents(); void DetachWebContents();
void ReattachForFullscreenChange(bool enter_fullscreen); void ReattachForFullscreenChange(bool enter_fullscreen);
void NotifyMaybeTextInputClientChanged(); void NotifyMaybeTextInputClientAndAccessibilityChanged();
// Create a regular or test web contents (based on whether we're running // Create a regular or test web contents (based on whether we're running
// in a unit test or not). // in a unit test or not).
......
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