OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All |
7 * rights reserved. | 7 * rights reserved. |
8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. | 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. |
9 * (http://www.torchmobile.com/) | 9 * (http://www.torchmobile.com/) |
10 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) | 10 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) |
(...skipping 30 matching lines...) Expand all Loading... | |
41 #include "core/html/HTMLIFrameElement.h" | 41 #include "core/html/HTMLIFrameElement.h" |
42 #include "core/input/EventHandler.h" | 42 #include "core/input/EventHandler.h" |
43 #include "core/inspector/ConsoleMessage.h" | 43 #include "core/inspector/ConsoleMessage.h" |
44 #include "core/layout/LayoutBlockFlow.h" | 44 #include "core/layout/LayoutBlockFlow.h" |
45 #include "core/layout/LayoutFullScreen.h" | 45 #include "core/layout/LayoutFullScreen.h" |
46 #include "core/layout/api/LayoutFullScreenItem.h" | 46 #include "core/layout/api/LayoutFullScreenItem.h" |
47 #include "core/page/ChromeClient.h" | 47 #include "core/page/ChromeClient.h" |
48 #include "core/svg/SVGSVGElement.h" | 48 #include "core/svg/SVGSVGElement.h" |
49 #include "platform/ScopedOrientationChangeIndicator.h" | 49 #include "platform/ScopedOrientationChangeIndicator.h" |
50 #include "platform/UserGestureIndicator.h" | 50 #include "platform/UserGestureIndicator.h" |
51 #include "public/platform/WebFullscreenCallbacks.h" | |
51 | 52 |
52 namespace blink { | 53 namespace blink { |
53 | 54 |
54 namespace { | 55 namespace { |
55 | 56 |
56 // https://html.spec.whatwg.org/multipage/embedded-content.html#allowed-to-use | 57 // https://html.spec.whatwg.org/multipage/embedded-content.html#allowed-to-use |
57 bool allowedToUseFullscreen(const Frame* frame) { | 58 bool allowedToUseFullscreen(const Frame* frame) { |
58 // To determine whether a Document object |document| is allowed to use the | 59 // To determine whether a Document object |document| is allowed to use the |
59 // feature indicated by attribute name |allowattribute|, run these steps: | 60 // feature indicated by attribute name |allowattribute|, run these steps: |
60 | 61 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
179 // works even in OOPIF scenarios like A-B-A, where there may be remote frames | 180 // works even in OOPIF scenarios like A-B-A, where there may be remote frames |
180 // in between |doc| and |descendant|. | 181 // in between |doc| and |descendant|. |
181 HTMLFrameOwnerElement* findContainerForDescendant(const Document& doc, | 182 HTMLFrameOwnerElement* findContainerForDescendant(const Document& doc, |
182 const Document& descendant) { | 183 const Document& descendant) { |
183 Frame* frame = descendant.frame(); | 184 Frame* frame = descendant.frame(); |
184 while (frame->tree().parent() != doc.frame()) | 185 while (frame->tree().parent() != doc.frame()) |
185 frame = frame->tree().parent(); | 186 frame = frame->tree().parent(); |
186 return toHTMLFrameOwnerElement(frame->owner()); | 187 return toHTMLFrameOwnerElement(frame->owner()); |
187 } | 188 } |
188 | 189 |
190 class FullscreenCallbacks final : public WebFullscreenCallbacks { | |
191 // FIXME(tasak): When making public/platform classes to use PartitionAlloc, | |
192 // the following macro should be moved to WebCallbacks defined in | |
193 // public/platform/WebCallbacks.h. | |
194 USING_FAST_MALLOC(FullscreenCallbacks); | |
195 WTF_MAKE_NONCOPYABLE(FullscreenCallbacks); | |
196 | |
197 public: | |
198 FullscreenCallbacks(std::unique_ptr<WTF::Closure> success, | |
199 std::unique_ptr<WTF::Closure> error) | |
200 : m_success(std::move(success)), m_error(std::move(error)) {} | |
201 void onSuccess() override { (*m_success)(); } | |
202 void onError() override { (*m_error)(); } | |
203 | |
204 private: | |
205 std::unique_ptr<WTF::Closure> m_success; | |
206 std::unique_ptr<WTF::Closure> m_error; | |
207 }; | |
208 | |
189 } // anonymous namespace | 209 } // anonymous namespace |
190 | 210 |
191 const char* Fullscreen::supplementName() { | 211 const char* Fullscreen::supplementName() { |
192 return "Fullscreen"; | 212 return "Fullscreen"; |
193 } | 213 } |
194 | 214 |
195 Fullscreen& Fullscreen::from(Document& document) { | 215 Fullscreen& Fullscreen::from(Document& document) { |
196 Fullscreen* fullscreen = fromIfExists(document); | 216 Fullscreen* fullscreen = fromIfExists(document); |
197 if (!fullscreen) { | 217 if (!fullscreen) { |
198 fullscreen = new Fullscreen(document); | 218 fullscreen = new Fullscreen(document); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
291 if (!forCrossProcessDescendant) { | 311 if (!forCrossProcessDescendant) { |
292 if (document.isSecureContext()) { | 312 if (document.isSecureContext()) { |
293 UseCounter::count(document, UseCounter::FullscreenSecureOrigin); | 313 UseCounter::count(document, UseCounter::FullscreenSecureOrigin); |
294 } else { | 314 } else { |
295 UseCounter::count(document, UseCounter::FullscreenInsecureOrigin); | 315 UseCounter::count(document, UseCounter::FullscreenInsecureOrigin); |
296 HostsUsingFeatures::countAnyWorld( | 316 HostsUsingFeatures::countAnyWorld( |
297 document, HostsUsingFeatures::Feature::FullscreenInsecureHost); | 317 document, HostsUsingFeatures::Feature::FullscreenInsecureHost); |
298 } | 318 } |
299 } | 319 } |
300 | 320 |
301 // Ignore this request if the document is not in a live frame. | 321 // Ignore this call if the document is not in a live frame. |
302 if (!document.isActive()) | 322 if (!document.isActive() || !document.frame()) |
303 return; | 323 return; |
304 | 324 |
305 // If |element| is on top of |doc|'s fullscreen element stack, terminate these | 325 // If |element| is on top of |doc|'s fullscreen element stack, terminate these |
306 // substeps. | 326 // substeps. |
307 if (&element == fullscreenElementFrom(document)) | 327 if (&element == fullscreenElementFrom(document)) |
308 return; | 328 return; |
309 | 329 |
310 do { | 330 do { |
311 // 1. If any of the following conditions are false, then terminate these | 331 // 1. If any of the following conditions are false, then terminate these |
312 // steps and queue a task to fire an event named fullscreenerror with its | 332 // steps and queue a task to fire an event named fullscreenerror with its |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
392 continue; | 412 continue; |
393 } | 413 } |
394 | 414 |
395 // 4. Otherwise, do nothing for this document. It stays the same. | 415 // 4. Otherwise, do nothing for this document. It stays the same. |
396 } while (++current != docs.end()); | 416 } while (++current != docs.end()); |
397 | 417 |
398 from(document).m_forCrossProcessDescendant = forCrossProcessDescendant; | 418 from(document).m_forCrossProcessDescendant = forCrossProcessDescendant; |
399 | 419 |
400 // 5. Return, and run the remaining steps asynchronously. | 420 // 5. Return, and run the remaining steps asynchronously. |
401 // 6. Optionally, perform some animation. | 421 // 6. Optionally, perform some animation. |
402 document.frameHost()->chromeClient().enterFullscreenForElement(&element); | 422 document.frameHost()->chromeClient().enterFullscreen( |
423 *document.frame(), | |
424 wrapUnique(new FullscreenCallbacks( | |
mlamouri (slow - plz ping)
2016/11/30 09:24:57
Any particular reason why not keepinp track of `do
foolip
2016/11/30 10:23:52
This is a wart from before when I was using callba
| |
425 WTF::bind(&Fullscreen::didEnterFullscreenForElement, | |
426 wrapPersistent(&from(document)), | |
427 wrapPersistent(&element)), | |
428 WTF::bind(&Fullscreen::enqueueErrorEvent, | |
429 wrapPersistent(&from(document)), wrapPersistent(&element), | |
430 requestType)))); | |
403 | 431 |
404 // 7. Optionally, display a message indicating how the user can exit | 432 // 7. Optionally, display a message indicating how the user can exit |
405 // displaying the context object fullscreen. | 433 // displaying the context object fullscreen. |
406 return; | 434 return; |
407 } while (false); | 435 } while (false); |
408 | 436 |
409 from(document).enqueueErrorEvent(element, requestType); | 437 from(document).enqueueErrorEvent(&element, requestType); |
410 } | 438 } |
411 | 439 |
412 // https://fullscreen.spec.whatwg.org/#fully-exit-fullscreen | 440 // https://fullscreen.spec.whatwg.org/#fully-exit-fullscreen |
413 void Fullscreen::fullyExitFullscreen(Document& document) { | 441 void Fullscreen::fullyExitFullscreen(Document& document) { |
414 // To fully exit fullscreen, run these steps: | 442 // To fully exit fullscreen, run these steps: |
415 | 443 |
416 // 1. Let |doc| be the top-level browsing context's document. | 444 // 1. Let |doc| be the top-level browsing context's document. |
417 // | 445 // |
418 // Since the top-level browsing context's document might be unavailable in | 446 // Since the top-level browsing context's document might be unavailable in |
419 // OOPIF scenarios (i.e., when the top frame is remote), this actually uses | 447 // OOPIF scenarios (i.e., when the top frame is remote), this actually uses |
(...skipping 14 matching lines...) Expand all Loading... | |
434 DCHECK_EQ(from(doc).m_fullscreenElementStack.size(), 1u); | 462 DCHECK_EQ(from(doc).m_fullscreenElementStack.size(), 1u); |
435 | 463 |
436 // 4. Act as if the exitFullscreen() method was invoked on |doc|. | 464 // 4. Act as if the exitFullscreen() method was invoked on |doc|. |
437 exitFullscreen(doc); | 465 exitFullscreen(doc); |
438 } | 466 } |
439 | 467 |
440 // https://fullscreen.spec.whatwg.org/#exit-fullscreen | 468 // https://fullscreen.spec.whatwg.org/#exit-fullscreen |
441 void Fullscreen::exitFullscreen(Document& document) { | 469 void Fullscreen::exitFullscreen(Document& document) { |
442 // The exitFullscreen() method must run these steps: | 470 // The exitFullscreen() method must run these steps: |
443 | 471 |
444 // 1. Let doc be the context object. (i.e. "this") | 472 // Ignore this call if the document is not in a live frame. |
445 if (!document.isActive()) | 473 if (!document.isActive() || !document.frame()) |
446 return; | 474 return; |
447 | 475 |
476 // 1. Let doc be the context object. (i.e. "this") | |
448 // 2. If doc's fullscreen element stack is empty, terminate these steps. | 477 // 2. If doc's fullscreen element stack is empty, terminate these steps. |
449 if (!fullscreenElementFrom(document)) | 478 if (!fullscreenElementFrom(document)) |
450 return; | 479 return; |
451 | 480 |
452 // 3. Let descendants be all the doc's descendant browsing context's documents | 481 // 3. Let descendants be all the doc's descendant browsing context's documents |
453 // with a non-empty fullscreen element stack (if any), ordered so that the | 482 // with a non-empty fullscreen element stack (if any), ordered so that the |
454 // child of the doc is last and the document furthest away from the doc is | 483 // child of the doc is last and the document furthest away from the doc is |
455 // first. | 484 // first. |
456 HeapDeque<Member<Document>> descendants; | 485 HeapDeque<Member<Document>> descendants; |
457 for (Frame* descendant = | 486 for (Frame* descendant = document.frame()->tree().traverseNext(); descendant; |
458 document.frame() ? document.frame()->tree().traverseNext() : nullptr; | 487 descendant = descendant->tree().traverseNext()) { |
459 descendant; descendant = descendant->tree().traverseNext()) { | |
460 if (!descendant->isLocalFrame()) | 488 if (!descendant->isLocalFrame()) |
461 continue; | 489 continue; |
462 DCHECK(toLocalFrame(descendant)->document()); | 490 DCHECK(toLocalFrame(descendant)->document()); |
463 if (fullscreenElementFrom(*toLocalFrame(descendant)->document())) | 491 if (fullscreenElementFrom(*toLocalFrame(descendant)->document())) |
464 descendants.prepend(toLocalFrame(descendant)->document()); | 492 descendants.prepend(toLocalFrame(descendant)->document()); |
465 } | 493 } |
466 | 494 |
467 // 4. For each descendant in descendants, empty descendant's fullscreen | 495 // 4. For each descendant in descendants, empty descendant's fullscreen |
468 // element stack, and queue a task to fire an event named fullscreenchange | 496 // element stack, and queue a task to fire an event named fullscreenchange |
469 // with its bubbles attribute set to true on descendant. | 497 // with its bubbles attribute set to true on descendant. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
522 // 7. Optionally, perform some animation. | 550 // 7. Optionally, perform some animation. |
523 | 551 |
524 FrameHost* host = document.frameHost(); | 552 FrameHost* host = document.frameHost(); |
525 | 553 |
526 // Speculative fix for engaget.com/videos per crbug.com/336239. | 554 // Speculative fix for engaget.com/videos per crbug.com/336239. |
527 // FIXME: This check is wrong. We DCHECK(document->isActive()) above | 555 // FIXME: This check is wrong. We DCHECK(document->isActive()) above |
528 // so this should be redundant and should be removed! | 556 // so this should be redundant and should be removed! |
529 if (!host) | 557 if (!host) |
530 return; | 558 return; |
531 | 559 |
532 // Only exit out of full screen window mode if there are no remaining elements | 560 // Only exit fullscreen mode if the fullscreen element stack is empty. |
533 // in the full screen stack. | |
534 if (!newTop) { | 561 if (!newTop) { |
535 host->chromeClient().exitFullscreen(document.frame()); | 562 host->chromeClient().exitFullscreen(*document.frame()); |
536 return; | 563 return; |
537 } | 564 } |
538 | 565 |
539 // Otherwise, notify the chrome of the new full screen element. | 566 // Otherwise, enter fullscreen for the fullscreen element stack's top element. |
540 host->chromeClient().enterFullscreenForElement(newTop); | 567 from(document).didEnterFullscreenForElement(newTop); |
541 } | 568 } |
542 | 569 |
543 // https://fullscreen.spec.whatwg.org/#dom-document-fullscreenenabled | 570 // https://fullscreen.spec.whatwg.org/#dom-document-fullscreenenabled |
544 bool Fullscreen::fullscreenEnabled(Document& document) { | 571 bool Fullscreen::fullscreenEnabled(Document& document) { |
545 // The fullscreenEnabled attribute's getter must return true if the context | 572 // The fullscreenEnabled attribute's getter must return true if the context |
546 // object is allowed to use the feature indicated by attribute name | 573 // object is allowed to use the feature indicated by attribute name |
547 // allowfullscreen and fullscreen is supported, and false otherwise. | 574 // allowfullscreen and fullscreen is supported, and false otherwise. |
548 return allowedToUseFullscreen(document.frame()) && | 575 return allowedToUseFullscreen(document.frame()) && |
549 fullscreenIsSupported(document); | 576 fullscreenIsSupported(document); |
550 } | 577 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
609 element); | 636 element); |
610 } | 637 } |
611 | 638 |
612 void Fullscreen::didExitFullscreen() { | 639 void Fullscreen::didExitFullscreen() { |
613 if (!document()->isActive() || !document()->frame()) | 640 if (!document()->isActive() || !document()->frame()) |
614 return; | 641 return; |
615 | 642 |
616 if (!m_currentFullScreenElement) | 643 if (!m_currentFullScreenElement) |
617 return; | 644 return; |
618 | 645 |
646 // If fullscreen was canceled by the browser, e.g. if the user pressed Esc, | |
647 // then |exitFullscreen()| was never called. Let |fullyExitFullscreen()| clear | |
648 // the fullscreen element stack and fire any events as necessary. | |
649 // TODO(foolip): Remove this when state changes and events are synchronized | |
650 // with animation frames. https://crbug.com/402376 | |
651 fullyExitFullscreen(*document()); | |
652 | |
619 if (m_forCrossProcessDescendant) | 653 if (m_forCrossProcessDescendant) |
620 m_currentFullScreenElement->setContainsFullScreenElement(false); | 654 m_currentFullScreenElement->setContainsFullScreenElement(false); |
621 | 655 |
622 m_currentFullScreenElement | 656 m_currentFullScreenElement |
623 ->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false); | 657 ->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false); |
624 | 658 |
625 if (m_fullScreenLayoutObject) | 659 if (m_fullScreenLayoutObject) |
626 LayoutFullScreenItem(m_fullScreenLayoutObject).unwrapLayoutObject(); | 660 LayoutFullScreenItem(m_fullScreenLayoutObject).unwrapLayoutObject(); |
627 | 661 |
628 document()->styleEngine().ensureUAStyleForFullscreen(); | 662 document()->styleEngine().ensureUAStyleForFullscreen(); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
686 target = fullscreen.currentFullScreenElement(); | 720 target = fullscreen.currentFullScreenElement(); |
687 if (!target) | 721 if (!target) |
688 target = &document; | 722 target = &document; |
689 event = createEvent(EventTypeNames::webkitfullscreenchange, *target); | 723 event = createEvent(EventTypeNames::webkitfullscreenchange, *target); |
690 } | 724 } |
691 m_eventQueue.append(event); | 725 m_eventQueue.append(event); |
692 // NOTE: The timer is started in | 726 // NOTE: The timer is started in |
693 // didEnterFullscreenForElement/didExitFullscreen. | 727 // didEnterFullscreenForElement/didExitFullscreen. |
694 } | 728 } |
695 | 729 |
696 void Fullscreen::enqueueErrorEvent(Element& element, RequestType requestType) { | 730 void Fullscreen::enqueueErrorEvent(Element* element, RequestType requestType) { |
731 DCHECK(element); | |
732 | |
697 Event* event; | 733 Event* event; |
698 if (requestType == UnprefixedRequest) | 734 if (requestType == UnprefixedRequest) |
699 event = createEvent(EventTypeNames::fullscreenerror, element.document()); | 735 event = createEvent(EventTypeNames::fullscreenerror, element->document()); |
700 else | 736 else |
701 event = createEvent(EventTypeNames::webkitfullscreenerror, element); | 737 event = createEvent(EventTypeNames::webkitfullscreenerror, *element); |
702 m_eventQueue.append(event); | 738 m_eventQueue.append(event); |
703 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); | 739 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); |
704 } | 740 } |
705 | 741 |
706 void Fullscreen::eventQueueTimerFired(TimerBase*) { | 742 void Fullscreen::eventQueueTimerFired(TimerBase*) { |
707 HeapDeque<Member<Event>> eventQueue; | 743 HeapDeque<Member<Event>> eventQueue; |
708 m_eventQueue.swap(eventQueue); | 744 m_eventQueue.swap(eventQueue); |
709 | 745 |
710 while (!eventQueue.isEmpty()) { | 746 while (!eventQueue.isEmpty()) { |
711 Event* event = eventQueue.takeFirst(); | 747 Event* event = eventQueue.takeFirst(); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
764 | 800 |
765 DEFINE_TRACE(Fullscreen) { | 801 DEFINE_TRACE(Fullscreen) { |
766 visitor->trace(m_currentFullScreenElement); | 802 visitor->trace(m_currentFullScreenElement); |
767 visitor->trace(m_fullscreenElementStack); | 803 visitor->trace(m_fullscreenElementStack); |
768 visitor->trace(m_eventQueue); | 804 visitor->trace(m_eventQueue); |
769 Supplement<Document>::trace(visitor); | 805 Supplement<Document>::trace(visitor); |
770 ContextLifecycleObserver::trace(visitor); | 806 ContextLifecycleObserver::trace(visitor); |
771 } | 807 } |
772 | 808 |
773 } // namespace blink | 809 } // namespace blink |
OLD | NEW |