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 13 matching lines...) Expand all Loading... | |
24 * along with this library; see the file COPYING.LIB. If not, write to | 24 * along with this library; see the file COPYING.LIB. If not, write to |
25 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 25 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
26 * Boston, MA 02110-1301, USA. | 26 * Boston, MA 02110-1301, USA. |
27 * | 27 * |
28 */ | 28 */ |
29 | 29 |
30 #include "core/dom/Fullscreen.h" | 30 #include "core/dom/Fullscreen.h" |
31 | 31 |
32 #include "core/dom/Document.h" | 32 #include "core/dom/Document.h" |
33 #include "core/dom/ElementTraversal.h" | 33 #include "core/dom/ElementTraversal.h" |
34 #include "core/dom/FullscreenCallbacks.h" | |
34 #include "core/dom/StyleEngine.h" | 35 #include "core/dom/StyleEngine.h" |
35 #include "core/events/Event.h" | 36 #include "core/events/Event.h" |
36 #include "core/frame/FrameHost.h" | 37 #include "core/frame/FrameHost.h" |
37 #include "core/frame/HostsUsingFeatures.h" | 38 #include "core/frame/HostsUsingFeatures.h" |
38 #include "core/frame/LocalFrame.h" | 39 #include "core/frame/LocalFrame.h" |
39 #include "core/frame/Settings.h" | 40 #include "core/frame/Settings.h" |
40 #include "core/frame/UseCounter.h" | 41 #include "core/frame/UseCounter.h" |
41 #include "core/html/HTMLIFrameElement.h" | 42 #include "core/html/HTMLIFrameElement.h" |
42 #include "core/input/EventHandler.h" | 43 #include "core/input/EventHandler.h" |
43 #include "core/inspector/ConsoleMessage.h" | 44 #include "core/inspector/ConsoleMessage.h" |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
273 void Fullscreen::contextDestroyed() { | 274 void Fullscreen::contextDestroyed() { |
274 m_eventQueue.clear(); | 275 m_eventQueue.clear(); |
275 | 276 |
276 if (m_fullScreenLayoutObject) | 277 if (m_fullScreenLayoutObject) |
277 m_fullScreenLayoutObject->destroy(); | 278 m_fullScreenLayoutObject->destroy(); |
278 | 279 |
279 m_currentFullScreenElement = nullptr; | 280 m_currentFullScreenElement = nullptr; |
280 m_fullscreenElementStack.clear(); | 281 m_fullscreenElementStack.clear(); |
281 } | 282 } |
282 | 283 |
284 // RequestFullscreenCallbacks hold the data for a pending request. | |
285 // FullscreenController invokes the success or error callback. | |
286 class RequestFullscreenCallbacks final : public FullscreenCallbacks { | |
287 USING_FAST_MALLOC(RequestFullscreenCallbacks); | |
288 WTF_MAKE_NONCOPYABLE(RequestFullscreenCallbacks); | |
289 | |
290 public: | |
291 static std::unique_ptr<FullscreenCallbacks> | |
292 create(Document& document, Element& element, Fullscreen::RequestType type) { | |
293 return wrapUnique(new RequestFullscreenCallbacks(Fullscreen::from(document), | |
esprehn
2016/12/01 20:26:12
The element and the document can disagree, is ther
foolip
2016/12/01 23:05:01
I was working on this today, just uploaded "handle
| |
294 element, type)); | |
295 } | |
296 void onSuccess() override { m_fullscreen->didEnterFullscreen(*m_element); } | |
297 void onError() override { | |
298 m_fullscreen->enqueueErrorEvent(*m_element, m_type); | |
299 } | |
300 | |
301 private: | |
302 RequestFullscreenCallbacks(Fullscreen& fullscreen, | |
303 Element& element, | |
304 Fullscreen::RequestType type) | |
305 : m_fullscreen(fullscreen), m_element(element), m_type(type) {} | |
306 Persistent<Fullscreen> m_fullscreen; | |
307 Persistent<Element> m_element; | |
308 Fullscreen::RequestType m_type; | |
309 }; | |
310 | |
283 // https://fullscreen.spec.whatwg.org/#dom-element-requestfullscreen | 311 // https://fullscreen.spec.whatwg.org/#dom-element-requestfullscreen |
284 void Fullscreen::requestFullscreen(Element& element, | 312 void Fullscreen::requestFullscreen(Element& element, |
285 RequestType requestType, | 313 RequestType requestType, |
286 bool forCrossProcessDescendant) { | 314 bool forCrossProcessDescendant) { |
287 Document& document = element.document(); | 315 Document& document = element.document(); |
288 | 316 |
289 // Use counters only need to be incremented in the process of the actual | 317 // Use counters only need to be incremented in the process of the actual |
290 // fullscreen element. | 318 // fullscreen element. |
291 if (!forCrossProcessDescendant) { | 319 if (!forCrossProcessDescendant) { |
292 if (document.isSecureContext()) { | 320 if (document.isSecureContext()) { |
293 UseCounter::count(document, UseCounter::FullscreenSecureOrigin); | 321 UseCounter::count(document, UseCounter::FullscreenSecureOrigin); |
294 } else { | 322 } else { |
295 UseCounter::count(document, UseCounter::FullscreenInsecureOrigin); | 323 UseCounter::count(document, UseCounter::FullscreenInsecureOrigin); |
296 HostsUsingFeatures::countAnyWorld( | 324 HostsUsingFeatures::countAnyWorld( |
297 document, HostsUsingFeatures::Feature::FullscreenInsecureHost); | 325 document, HostsUsingFeatures::Feature::FullscreenInsecureHost); |
298 } | 326 } |
299 } | 327 } |
300 | 328 |
301 // Ignore this request if the document is not in a live frame. | 329 // Ignore this call if the document is not in a live frame. |
302 if (!document.isActive()) | 330 if (!document.isActive() || !document.frame()) |
303 return; | 331 return; |
304 | 332 |
305 // If |element| is on top of |doc|'s fullscreen element stack, terminate these | 333 // If |element| is on top of |doc|'s fullscreen element stack, terminate these |
306 // substeps. | 334 // substeps. |
307 if (&element == fullscreenElementFrom(document)) | 335 if (&element == fullscreenElementFrom(document)) |
308 return; | 336 return; |
309 | 337 |
310 do { | 338 do { |
311 // 1. If any of the following conditions are false, then terminate these | 339 // 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 | 340 // 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; | 420 continue; |
393 } | 421 } |
394 | 422 |
395 // 4. Otherwise, do nothing for this document. It stays the same. | 423 // 4. Otherwise, do nothing for this document. It stays the same. |
396 } while (++current != docs.end()); | 424 } while (++current != docs.end()); |
397 | 425 |
398 from(document).m_forCrossProcessDescendant = forCrossProcessDescendant; | 426 from(document).m_forCrossProcessDescendant = forCrossProcessDescendant; |
399 | 427 |
400 // 5. Return, and run the remaining steps asynchronously. | 428 // 5. Return, and run the remaining steps asynchronously. |
401 // 6. Optionally, perform some animation. | 429 // 6. Optionally, perform some animation. |
402 document.frameHost()->chromeClient().enterFullscreenForElement(&element); | 430 document.frameHost()->chromeClient().enterFullscreen( |
431 *document.frame(), | |
432 RequestFullscreenCallbacks::create(document, element, requestType)); | |
403 | 433 |
404 // 7. Optionally, display a message indicating how the user can exit | 434 // 7. Optionally, display a message indicating how the user can exit |
405 // displaying the context object fullscreen. | 435 // displaying the context object fullscreen. |
406 return; | 436 return; |
407 } while (false); | 437 } while (false); |
408 | 438 |
409 from(document).enqueueErrorEvent(element, requestType); | 439 from(document).enqueueErrorEvent(element, requestType); |
410 } | 440 } |
411 | 441 |
412 // https://fullscreen.spec.whatwg.org/#fully-exit-fullscreen | 442 // https://fullscreen.spec.whatwg.org/#fully-exit-fullscreen |
(...skipping 21 matching lines...) Expand all Loading... | |
434 DCHECK_EQ(from(doc).m_fullscreenElementStack.size(), 1u); | 464 DCHECK_EQ(from(doc).m_fullscreenElementStack.size(), 1u); |
435 | 465 |
436 // 4. Act as if the exitFullscreen() method was invoked on |doc|. | 466 // 4. Act as if the exitFullscreen() method was invoked on |doc|. |
437 exitFullscreen(doc); | 467 exitFullscreen(doc); |
438 } | 468 } |
439 | 469 |
440 // https://fullscreen.spec.whatwg.org/#exit-fullscreen | 470 // https://fullscreen.spec.whatwg.org/#exit-fullscreen |
441 void Fullscreen::exitFullscreen(Document& document) { | 471 void Fullscreen::exitFullscreen(Document& document) { |
442 // The exitFullscreen() method must run these steps: | 472 // The exitFullscreen() method must run these steps: |
443 | 473 |
444 // 1. Let doc be the context object. (i.e. "this") | 474 // Ignore this call if the document is not in a live frame. |
445 if (!document.isActive()) | 475 if (!document.isActive() || !document.frame()) |
446 return; | 476 return; |
447 | 477 |
478 // 1. Let doc be the context object. (i.e. "this") | |
448 // 2. If doc's fullscreen element stack is empty, terminate these steps. | 479 // 2. If doc's fullscreen element stack is empty, terminate these steps. |
449 if (!fullscreenElementFrom(document)) | 480 if (!fullscreenElementFrom(document)) |
450 return; | 481 return; |
451 | 482 |
452 // 3. Let descendants be all the doc's descendant browsing context's documents | 483 // 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 | 484 // 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 | 485 // child of the doc is last and the document furthest away from the doc is |
455 // first. | 486 // first. |
456 HeapDeque<Member<Document>> descendants; | 487 HeapDeque<Member<Document>> descendants; |
457 for (Frame* descendant = | 488 for (Frame* descendant = document.frame()->tree().traverseNext(); descendant; |
458 document.frame() ? document.frame()->tree().traverseNext() : nullptr; | 489 descendant = descendant->tree().traverseNext()) { |
459 descendant; descendant = descendant->tree().traverseNext()) { | |
460 if (!descendant->isLocalFrame()) | 490 if (!descendant->isLocalFrame()) |
461 continue; | 491 continue; |
462 DCHECK(toLocalFrame(descendant)->document()); | 492 DCHECK(toLocalFrame(descendant)->document()); |
463 if (fullscreenElementFrom(*toLocalFrame(descendant)->document())) | 493 if (fullscreenElementFrom(*toLocalFrame(descendant)->document())) |
464 descendants.prepend(toLocalFrame(descendant)->document()); | 494 descendants.prepend(toLocalFrame(descendant)->document()); |
465 } | 495 } |
466 | 496 |
467 // 4. For each descendant in descendants, empty descendant's fullscreen | 497 // 4. For each descendant in descendants, empty descendant's fullscreen |
468 // element stack, and queue a task to fire an event named fullscreenchange | 498 // element stack, and queue a task to fire an event named fullscreenchange |
469 // with its bubbles attribute set to true on descendant. | 499 // 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. | 552 // 7. Optionally, perform some animation. |
523 | 553 |
524 FrameHost* host = document.frameHost(); | 554 FrameHost* host = document.frameHost(); |
525 | 555 |
526 // Speculative fix for engaget.com/videos per crbug.com/336239. | 556 // Speculative fix for engaget.com/videos per crbug.com/336239. |
527 // FIXME: This check is wrong. We DCHECK(document->isActive()) above | 557 // FIXME: This check is wrong. We DCHECK(document->isActive()) above |
528 // so this should be redundant and should be removed! | 558 // so this should be redundant and should be removed! |
529 if (!host) | 559 if (!host) |
530 return; | 560 return; |
531 | 561 |
532 // Only exit out of full screen window mode if there are no remaining elements | 562 // Only exit fullscreen mode if the fullscreen element stack is empty. |
533 // in the full screen stack. | |
534 if (!newTop) { | 563 if (!newTop) { |
535 host->chromeClient().exitFullscreen(document.frame()); | 564 host->chromeClient().exitFullscreen(*document.frame()); |
536 return; | 565 return; |
537 } | 566 } |
538 | 567 |
539 // Otherwise, notify the chrome of the new full screen element. | 568 // Otherwise, enter fullscreen for the fullscreen element stack's top element. |
540 host->chromeClient().enterFullscreenForElement(newTop); | 569 from(document).didEnterFullscreen(*newTop); |
541 } | 570 } |
542 | 571 |
543 // https://fullscreen.spec.whatwg.org/#dom-document-fullscreenenabled | 572 // https://fullscreen.spec.whatwg.org/#dom-document-fullscreenenabled |
544 bool Fullscreen::fullscreenEnabled(Document& document) { | 573 bool Fullscreen::fullscreenEnabled(Document& document) { |
545 // The fullscreenEnabled attribute's getter must return true if the context | 574 // The fullscreenEnabled attribute's getter must return true if the context |
546 // object is allowed to use the feature indicated by attribute name | 575 // object is allowed to use the feature indicated by attribute name |
547 // allowfullscreen and fullscreen is supported, and false otherwise. | 576 // allowfullscreen and fullscreen is supported, and false otherwise. |
548 return allowedToUseFullscreen(document.frame()) && | 577 return allowedToUseFullscreen(document.frame()) && |
549 fullscreenIsSupported(document); | 578 fullscreenIsSupported(document); |
550 } | 579 } |
551 | 580 |
552 void Fullscreen::didEnterFullscreenForElement(Element* element) { | 581 void Fullscreen::didEnterFullscreen(Element& element) { |
553 DCHECK(element); | |
554 if (!document()->isActive() || !document()->frame()) | 582 if (!document()->isActive() || !document()->frame()) |
555 return; | 583 return; |
556 | 584 |
557 if (m_currentFullScreenElement == element) | 585 if (m_currentFullScreenElement == &element) |
558 return; | 586 return; |
559 | 587 |
560 if (m_fullScreenLayoutObject) | 588 if (m_fullScreenLayoutObject) |
561 m_fullScreenLayoutObject->unwrapLayoutObject(); | 589 m_fullScreenLayoutObject->unwrapLayoutObject(); |
562 | 590 |
563 Element* previousElement = m_currentFullScreenElement; | 591 Element* previousElement = m_currentFullScreenElement; |
564 m_currentFullScreenElement = element; | 592 m_currentFullScreenElement = &element; |
565 | 593 |
566 // Create a placeholder block for a the full-screen element, to keep the page | 594 // Create a placeholder block for a the full-screen element, to keep the page |
567 // from reflowing when the element is removed from the normal flow. Only do | 595 // from reflowing when the element is removed from the normal flow. Only do |
568 // this for a LayoutBox, as only a box will have a frameRect. The placeholder | 596 // this for a LayoutBox, as only a box will have a frameRect. The placeholder |
569 // will be created in setFullScreenLayoutObject() during layout. | 597 // will be created in setFullScreenLayoutObject() during layout. |
570 LayoutObject* layoutObject = m_currentFullScreenElement->layoutObject(); | 598 LayoutObject* layoutObject = m_currentFullScreenElement->layoutObject(); |
571 bool shouldCreatePlaceholder = layoutObject && layoutObject->isBox(); | 599 bool shouldCreatePlaceholder = layoutObject && layoutObject->isBox(); |
572 if (shouldCreatePlaceholder) { | 600 if (shouldCreatePlaceholder) { |
573 m_savedPlaceholderFrameRect = toLayoutBox(layoutObject)->frameRect(); | 601 m_savedPlaceholderFrameRect = toLayoutBox(layoutObject)->frameRect(); |
574 m_savedPlaceholderComputedStyle = | 602 m_savedPlaceholderComputedStyle = |
(...skipping 27 matching lines...) Expand all Loading... | |
602 m_currentFullScreenElement->pseudoStateChanged(CSSSelector::PseudoFullScreen); | 630 m_currentFullScreenElement->pseudoStateChanged(CSSSelector::PseudoFullScreen); |
603 | 631 |
604 // FIXME: This should not call updateStyleAndLayoutTree. | 632 // FIXME: This should not call updateStyleAndLayoutTree. |
605 document()->updateStyleAndLayoutTree(); | 633 document()->updateStyleAndLayoutTree(); |
606 | 634 |
607 document()->frame()->eventHandler().scheduleHoverStateUpdate(); | 635 document()->frame()->eventHandler().scheduleHoverStateUpdate(); |
608 | 636 |
609 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); | 637 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); |
610 | 638 |
611 document()->frame()->chromeClient().fullscreenElementChanged(previousElement, | 639 document()->frame()->chromeClient().fullscreenElementChanged(previousElement, |
612 element); | 640 &element); |
613 } | 641 } |
614 | 642 |
615 void Fullscreen::didExitFullscreen() { | 643 void Fullscreen::didExitFullscreen() { |
616 if (!document()->isActive() || !document()->frame()) | 644 if (!document()->isActive() || !document()->frame()) |
617 return; | 645 return; |
618 | 646 |
619 if (!m_currentFullScreenElement) | 647 if (!m_currentFullScreenElement) |
620 return; | 648 return; |
621 | 649 |
650 // If fullscreen was canceled by the browser, e.g. if the user pressed Esc, | |
651 // then |exitFullscreen()| was never called. Let |fullyExitFullscreen()| clear | |
652 // the fullscreen element stack and fire any events as necessary. | |
653 // TODO(foolip): Remove this when state changes and events are synchronized | |
654 // with animation frames. https://crbug.com/402376 | |
655 fullyExitFullscreen(*document()); | |
656 | |
622 if (m_forCrossProcessDescendant) | 657 if (m_forCrossProcessDescendant) |
623 m_currentFullScreenElement->setContainsFullScreenElement(false); | 658 m_currentFullScreenElement->setContainsFullScreenElement(false); |
624 | 659 |
625 m_currentFullScreenElement | 660 m_currentFullScreenElement |
626 ->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false); | 661 ->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false); |
627 | 662 |
628 if (m_fullScreenLayoutObject) | 663 if (m_fullScreenLayoutObject) |
629 LayoutFullScreenItem(m_fullScreenLayoutObject).unwrapLayoutObject(); | 664 LayoutFullScreenItem(m_fullScreenLayoutObject).unwrapLayoutObject(); |
630 | 665 |
631 document()->styleEngine().ensureUAStyleForFullscreen(); | 666 document()->styleEngine().ensureUAStyleForFullscreen(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
685 DCHECK(document.hasFullscreenSupplement()); | 720 DCHECK(document.hasFullscreenSupplement()); |
686 Fullscreen& fullscreen = from(document); | 721 Fullscreen& fullscreen = from(document); |
687 EventTarget* target = fullscreen.fullscreenElement(); | 722 EventTarget* target = fullscreen.fullscreenElement(); |
688 if (!target) | 723 if (!target) |
689 target = fullscreen.currentFullScreenElement(); | 724 target = fullscreen.currentFullScreenElement(); |
690 if (!target) | 725 if (!target) |
691 target = &document; | 726 target = &document; |
692 event = createEvent(EventTypeNames::webkitfullscreenchange, *target); | 727 event = createEvent(EventTypeNames::webkitfullscreenchange, *target); |
693 } | 728 } |
694 m_eventQueue.append(event); | 729 m_eventQueue.append(event); |
695 // NOTE: The timer is started in | 730 // NOTE: The timer is started in didEnterFullscreen/didExitFullscreen. |
696 // didEnterFullscreenForElement/didExitFullscreen. | |
697 } | 731 } |
698 | 732 |
699 void Fullscreen::enqueueErrorEvent(Element& element, RequestType requestType) { | 733 void Fullscreen::enqueueErrorEvent(Element& element, RequestType requestType) { |
700 Event* event; | 734 Event* event; |
701 if (requestType == UnprefixedRequest) | 735 if (requestType == UnprefixedRequest) |
702 event = createEvent(EventTypeNames::fullscreenerror, element.document()); | 736 event = createEvent(EventTypeNames::fullscreenerror, element.document()); |
703 else | 737 else |
704 event = createEvent(EventTypeNames::webkitfullscreenerror, element); | 738 event = createEvent(EventTypeNames::webkitfullscreenerror, element); |
705 m_eventQueue.append(event); | 739 m_eventQueue.append(event); |
706 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); | 740 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
767 | 801 |
768 DEFINE_TRACE(Fullscreen) { | 802 DEFINE_TRACE(Fullscreen) { |
769 visitor->trace(m_currentFullScreenElement); | 803 visitor->trace(m_currentFullScreenElement); |
770 visitor->trace(m_fullscreenElementStack); | 804 visitor->trace(m_fullscreenElementStack); |
771 visitor->trace(m_eventQueue); | 805 visitor->trace(m_eventQueue); |
772 Supplement<Document>::trace(visitor); | 806 Supplement<Document>::trace(visitor); |
773 ContextLifecycleObserver::trace(visitor); | 807 ContextLifecycleObserver::trace(visitor); |
774 } | 808 } |
775 | 809 |
776 } // namespace blink | 810 } // namespace blink |
OLD | NEW |