Chromium Code Reviews| Index: third_party/WebKit/Source/core/dom/Fullscreen.cpp |
| diff --git a/third_party/WebKit/Source/core/dom/Fullscreen.cpp b/third_party/WebKit/Source/core/dom/Fullscreen.cpp |
| index 36048968b60f50a073cf18c89738355f4b3e4e16..b0fe076274e810d0cd2e5bfe0f2e7732f20add84 100644 |
| --- a/third_party/WebKit/Source/core/dom/Fullscreen.cpp |
| +++ b/third_party/WebKit/Source/core/dom/Fullscreen.cpp |
| @@ -121,6 +121,18 @@ static Event* createEvent(const AtomicString& type, EventTarget& target) |
| return event; |
| } |
| +static Document& topmostDocument(Document& document) |
| +{ |
| + Document* topmost = &document; |
| + Frame* frame = document.frame(); |
| + while (frame) { |
| + frame = frame->tree().parent(); |
| + if (frame && frame->isLocalFrame()) |
| + topmost = toLocalFrame(frame)->document(); |
| + } |
| + return *topmost; |
| +} |
| + |
| const char* Fullscreen::supplementName() |
| { |
| return "Fullscreen"; |
| @@ -242,50 +254,53 @@ void Fullscreen::requestFullscreen(Element& element, RequestType requestType, bo |
| break; |
| // 2. Let doc be element's node document. (i.e. "this") |
| - Document* currentDoc = document(); |
| + Frame* currentFrame = document()->frame(); |
| // 3. Let docs be all doc's ancestor browsing context's documents (if any) and doc. |
| - HeapDeque<Member<Document>> docs; |
| + HeapDeque<Member<Frame>> ancestors; |
| do { |
| - docs.prepend(currentDoc); |
| - currentDoc = currentDoc->localOwner() ? ¤tDoc->localOwner()->document() : nullptr; |
| - } while (currentDoc); |
| + ancestors.prepend(currentFrame); |
| + currentFrame = currentFrame->tree().parent(); |
| + } while (currentFrame); |
| // 4. For each document in docs, run these substeps: |
| - HeapDeque<Member<Document>>::iterator current = docs.begin(), following = docs.begin(); |
| + HeapDeque<Member<Frame>>::iterator current = ancestors.begin(), following = ancestors.begin(); |
| do { |
| ++following; |
| // 1. Let following document be the document after document in docs, or null if there is no |
| // such document. |
| - Document* currentDoc = *current; |
| - Document* followingDoc = following != docs.end() ? *following : nullptr; |
| + Frame* currentFrame = *current; |
| + Frame* followingFrame = following != ancestors.end() ? *following : nullptr; |
| // 2. If following document is null, push context object on document's fullscreen element |
| // stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute |
| // set to true on the document. |
| - if (!followingDoc) { |
| - from(*currentDoc).pushFullscreenElementStack(element, requestType); |
| - enqueueChangeEvent(*currentDoc, requestType); |
| + if (!followingFrame) { |
| + from(*toLocalFrame(currentFrame)->document()).pushFullscreenElementStack(element, requestType); |
| + enqueueChangeEvent(*toLocalFrame(currentFrame)->document(), requestType); |
| continue; |
| } |
| // 3. Otherwise, if document's fullscreen element stack is either empty or its top element |
| // is not following document's browsing context container, |
| + if (currentFrame->isRemoteFrame()) |
| + continue; |
| + Document* currentDoc = toLocalFrame(currentFrame)->document(); |
| Element* topElement = fullscreenElementFrom(*currentDoc); |
| - if (!topElement || topElement != followingDoc->localOwner()) { |
| + if (!topElement || topElement != toHTMLFrameOwnerElement(followingFrame->owner())) { |
| // ...push following document's browsing context container on document's fullscreen element |
| // stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute |
| // set to true on document. |
| - from(*currentDoc).pushFullscreenElementStack(*followingDoc->localOwner(), requestType); |
| + from(*currentDoc).pushFullscreenElementStack(*toHTMLFrameOwnerElement(followingFrame->owner()), requestType); |
| enqueueChangeEvent(*currentDoc, requestType); |
| continue; |
| } |
| // 4. Otherwise, do nothing for this document. It stays the same. |
| - } while (++current != docs.end()); |
| + } while (++current != ancestors.end()); |
| m_forCrossProcessAncestor = forCrossProcessAncestor; |
| @@ -305,7 +320,11 @@ void Fullscreen::fullyExitFullscreen(Document& document) |
| // To fully exit fullscreen, run these steps: |
| // 1. Let |doc| be the top-level browsing context's document. |
| - Document& doc = document.topDocument(); |
| + // |
| + // For OOPIF, use the Document of the topmost local ancestor frame. Each |
| + // renderer process for the current page will separately call |
| + // fullyExitFullscreen. |
| + Document& doc = topmostDocument(document); |
|
alexmos
2016/06/06 22:23:49
topDocument() was wrong here - see https://crbug.c
|
| // 2. If |doc|'s fullscreen element stack is empty, terminate these steps. |
| if (!fullscreenElementFrom(doc)) |
| @@ -374,9 +393,19 @@ void Fullscreen::exitFullscreen() |
| // 3. If doc's fullscreen element stack is empty and doc's browsing context has a browsing context |
| // container, set doc to that browsing context container's node document. |
| - if (!newTop && currentDoc->localOwner()) { |
| - currentDoc = ¤tDoc->localOwner()->document(); |
| - continue; |
| + // |
| + // OOPIF: If browsing context container's document is in another |
| + // process, keep moving up the ancestor chain and looking for a |
| + // browsing context container with a local document. |
| + // TODO(alexmos): Deal with nested fullscreen cases. |
|
alexmos
2016/06/06 22:23:49
It appears that cross-frame nested fullscreen has
|
| + if (!newTop) { |
| + Frame* frame = currentDoc->frame()->tree().parent(); |
| + while (frame && frame->isRemoteFrame()) |
| + frame = frame->tree().parent(); |
| + if (frame) { |
| + currentDoc = toLocalFrame(frame)->document(); |
| + continue; |
| + } |
| } |
| // 4. Otherwise, set doc to null. |
| @@ -501,7 +530,7 @@ void Fullscreen::didExitFullScreenForElement() |
| // exiting document. |
| Document* exitingDocument = document(); |
| if (m_eventQueue.isEmpty()) |
| - exitingDocument = &document()->topDocument(); |
| + exitingDocument = &topmostDocument(*document()); |
| DCHECK(exitingDocument); |
| from(*exitingDocument).m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); |