| Index: third_party/WebKit/Source/core/page/FocusController.cpp
|
| diff --git a/third_party/WebKit/Source/core/page/FocusController.cpp b/third_party/WebKit/Source/core/page/FocusController.cpp
|
| index 4bde2a973602ff3a8b47548ee964adbf8b974499..d0a97c766d642b7b795dde89cc6186e43e788ff7 100644
|
| --- a/third_party/WebKit/Source/core/page/FocusController.cpp
|
| +++ b/third_party/WebKit/Source/core/page/FocusController.cpp
|
| @@ -43,6 +43,7 @@
|
| #include "core/frame/FrameView.h"
|
| #include "core/frame/LocalDOMWindow.h"
|
| #include "core/frame/LocalFrame.h"
|
| +#include "core/frame/RemoteFrame.h"
|
| #include "core/frame/Settings.h"
|
| #include "core/html/HTMLAreaElement.h"
|
| #include "core/html/HTMLImageElement.h"
|
| @@ -690,8 +691,13 @@ bool FocusController::advanceFocus(WebFocusType type, bool initialFocus, InputDe
|
| {
|
| switch (type) {
|
| case WebFocusTypeForward:
|
| - case WebFocusTypeBackward:
|
| - return advanceFocusInDocumentOrder(type, initialFocus, sourceCapabilities);
|
| + case WebFocusTypeBackward: {
|
| + // We should never hit this when a RemoteFrame is focused, since the key
|
| + // event that initiated focus advancement should've been routed to that
|
| + // frame's process from the beginning.
|
| + LocalFrame* startingFrame = toLocalFrame(focusedOrMainFrame());
|
| + return advanceFocusInDocumentOrder(startingFrame, nullptr, type, initialFocus, sourceCapabilities);
|
| + }
|
| case WebFocusTypeLeft:
|
| case WebFocusTypeRight:
|
| case WebFocusTypeUp:
|
| @@ -704,17 +710,30 @@ bool FocusController::advanceFocus(WebFocusType type, bool initialFocus, InputDe
|
| return false;
|
| }
|
|
|
| -bool FocusController::advanceFocusInDocumentOrder(WebFocusType type, bool initialFocus, InputDeviceCapabilities* sourceCapabilities)
|
| +bool FocusController::advanceFocusAcrossFrames(WebFocusType type, RemoteFrame* from, LocalFrame* to, InputDeviceCapabilities* sourceCapabilities)
|
| +{
|
| + // If we are shifting focus from a child frame to its parent, the
|
| + // child frame has no more focusable elements, and we should continue
|
| + // looking for focusable elements in the parent, starting from the <iframe>
|
| + // element of the child frame.
|
| + Node* startingNode = nullptr;
|
| + if (from->tree().parent() == to) {
|
| + ASSERT(from->owner()->isLocal());
|
| + startingNode = toHTMLFrameOwnerElement(from->owner());
|
| + }
|
| +
|
| + return advanceFocusInDocumentOrder(to, startingNode, type, false, sourceCapabilities);
|
| +}
|
| +
|
| +bool FocusController::advanceFocusInDocumentOrder(LocalFrame* frame, Node* startingNode, WebFocusType type, bool initialFocus, InputDeviceCapabilities* sourceCapabilities)
|
| {
|
| - // FIXME: Focus advancement won't work with externally rendered frames until after
|
| - // inter-frame focus control is moved out of Blink.
|
| - if (!focusedOrMainFrame()->isLocalFrame())
|
| - return false;
|
| - LocalFrame* frame = toLocalFrame(focusedOrMainFrame());
|
| ASSERT(frame);
|
| Document* document = frame->document();
|
|
|
| - Node* currentNode = document->focusedElement();
|
| + Node* currentNode = startingNode;
|
| + if (!currentNode)
|
| + currentNode = document->focusedElement();
|
| +
|
| // FIXME: Not quite correct when it comes to focus transitions leaving/entering the WebView itself
|
| bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEnabled();
|
|
|
| @@ -726,6 +745,14 @@ bool FocusController::advanceFocusInDocumentOrder(WebFocusType type, bool initia
|
| RefPtrWillBeRawPtr<Element> element = findFocusableElementAcrossFocusScopes(type, FocusNavigationScope::focusNavigationScopeOf(currentNode ? *currentNode : *document), currentNode);
|
|
|
| if (!element) {
|
| + // If there's a RemoteFrame on the ancestor chain, we need to continue
|
| + // searching for focusable elements there.
|
| + if (frame->localFrameRoot() != frame->tree().top()) {
|
| + document->clearFocusedElement();
|
| + toRemoteFrame(frame->localFrameRoot()->tree().parent())->advanceFocus(type, frame->localFrameRoot());
|
| + return true;
|
| + }
|
| +
|
| // We didn't find an element to focus, so we should try to pass focus to Chrome.
|
| if (!initialFocus && m_page->chromeClient().canTakeFocus(type)) {
|
| document->clearFocusedElement();
|
| @@ -760,6 +787,14 @@ bool FocusController::advanceFocusInDocumentOrder(WebFocusType type, bool initia
|
|
|
| document->clearFocusedElement();
|
| setFocusedFrame(owner->contentFrame());
|
| +
|
| + // If contentFrame is remote, continue the search for focusable
|
| + // elements in that frame's process.
|
| + // clearFocusedElement() fires events that might detach the
|
| + // contentFrame, hence the need to null-check it again.
|
| + if (owner->contentFrame() && owner->contentFrame()->isRemoteFrame())
|
| + toRemoteFrame(owner->contentFrame())->advanceFocus(type, frame);
|
| +
|
| return true;
|
| }
|
|
|
|
|