| 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 r
ights reserved. | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All r
ights reserved. |
| 7 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) | 7 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) |
| 8 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) | 8 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) |
| 9 * Copyright (C) 2013 Google Inc. All rights reserved. | 9 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 10 * | 10 * |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 return !document.settings() || document.settings()->fullscreenSupported(); | 64 return !document.settings() || document.settings()->fullscreenSupported(); |
| 65 } | 65 } |
| 66 | 66 |
| 67 static bool fullscreenIsSupported(const Document& document, const Element& eleme
nt) | 67 static bool fullscreenIsSupported(const Document& document, const Element& eleme
nt) |
| 68 { | 68 { |
| 69 if (!document.settings() || (document.settings()->disallowFullscreenForNonMe
diaElements() && !isHTMLMediaElement(element))) | 69 if (!document.settings() || (document.settings()->disallowFullscreenForNonMe
diaElements() && !isHTMLMediaElement(element))) |
| 70 return false; | 70 return false; |
| 71 return fullscreenIsSupported(document); | 71 return fullscreenIsSupported(document); |
| 72 } | 72 } |
| 73 | 73 |
| 74 static bool isPrefixed(const AtomicString& type) |
| 75 { |
| 76 return type == EventTypeNames::webkitfullscreenchange || type == EventTypeNa
mes::webkitfullscreenerror; |
| 77 } |
| 78 |
| 74 static PassRefPtrWillBeRawPtr<Event> createEvent(const AtomicString& type, Event
Target& target) | 79 static PassRefPtrWillBeRawPtr<Event> createEvent(const AtomicString& type, Event
Target& target) |
| 75 { | 80 { |
| 76 RefPtrWillBeRawPtr<Event> event = Event::createBubble(type); | 81 EventInit initializer; |
| 82 initializer.bubbles = isPrefixed(type); |
| 83 RefPtrWillBeRawPtr<Event> event = Event::create(type, initializer); |
| 77 event->setTarget(&target); | 84 event->setTarget(&target); |
| 78 return event; | 85 return event; |
| 79 } | 86 } |
| 80 | 87 |
| 81 const char* FullscreenElementStack::supplementName() | 88 const char* FullscreenElementStack::supplementName() |
| 82 { | 89 { |
| 83 return "FullscreenElementStack"; | 90 return "FullscreenElementStack"; |
| 84 } | 91 } |
| 85 | 92 |
| 86 FullscreenElementStack& FullscreenElementStack::from(Document& document) | 93 FullscreenElementStack& FullscreenElementStack::from(Document& document) |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 | 257 |
| 251 // 1. Let following document be the document after document in docs,
or null if there is no | 258 // 1. Let following document be the document after document in docs,
or null if there is no |
| 252 // such document. | 259 // such document. |
| 253 Document* currentDoc = *current; | 260 Document* currentDoc = *current; |
| 254 Document* followingDoc = following != docs.end() ? *following : 0; | 261 Document* followingDoc = following != docs.end() ? *following : 0; |
| 255 | 262 |
| 256 // 2. If following document is null, push context object on document
's fullscreen element | 263 // 2. If following document is null, push context object on document
's fullscreen element |
| 257 // stack, and queue a task to fire an event named fullscreenchange w
ith its bubbles attribute | 264 // stack, and queue a task to fire an event named fullscreenchange w
ith its bubbles attribute |
| 258 // set to true on the document. | 265 // set to true on the document. |
| 259 if (!followingDoc) { | 266 if (!followingDoc) { |
| 260 from(*currentDoc).pushFullscreenElementStack(element); | 267 from(*currentDoc).pushFullscreenElementStack(element, requestTyp
e); |
| 261 enqueueChangeEvent(*currentDoc); | 268 enqueueChangeEvent(*currentDoc, requestType); |
| 262 continue; | 269 continue; |
| 263 } | 270 } |
| 264 | 271 |
| 265 // 3. Otherwise, if document's fullscreen element stack is either em
pty or its top element | 272 // 3. Otherwise, if document's fullscreen element stack is either em
pty or its top element |
| 266 // is not following document's browsing context container, | 273 // is not following document's browsing context container, |
| 267 Element* topElement = fullscreenElementFrom(*currentDoc); | 274 Element* topElement = fullscreenElementFrom(*currentDoc); |
| 268 if (!topElement || topElement != followingDoc->ownerElement()) { | 275 if (!topElement || topElement != followingDoc->ownerElement()) { |
| 269 // ...push following document's browsing context container on do
cument's fullscreen element | 276 // ...push following document's browsing context container on do
cument's fullscreen element |
| 270 // stack, and queue a task to fire an event named fullscreenchan
ge with its bubbles attribute | 277 // stack, and queue a task to fire an event named fullscreenchan
ge with its bubbles attribute |
| 271 // set to true on document. | 278 // set to true on document. |
| 272 from(*currentDoc).pushFullscreenElementStack(*followingDoc->owne
rElement()); | 279 from(*currentDoc).pushFullscreenElementStack(*followingDoc->owne
rElement(), requestType); |
| 273 enqueueChangeEvent(*currentDoc); | 280 enqueueChangeEvent(*currentDoc, requestType); |
| 274 continue; | 281 continue; |
| 275 } | 282 } |
| 276 | 283 |
| 277 // 4. Otherwise, do nothing for this document. It stays the same. | 284 // 4. Otherwise, do nothing for this document. It stays the same. |
| 278 } while (++current != docs.end()); | 285 } while (++current != docs.end()); |
| 279 | 286 |
| 280 // 5. Return, and run the remaining steps asynchronously. | 287 // 5. Return, and run the remaining steps asynchronously. |
| 281 // 6. Optionally, perform some animation. | 288 // 6. Optionally, perform some animation. |
| 282 m_areKeysEnabledInFullScreen = requestType != PrefixedMozillaRequest &&
requestType != PrefixedVideoRequest; | 289 m_areKeysEnabledInFullScreen = requestType != PrefixedMozillaRequest &&
requestType != PrefixedVideoRequest; |
| 283 document()->frameHost()->chrome().client().enterFullScreenForElement(&el
ement); | 290 document()->frameHost()->chrome().client().enterFullScreenForElement(&el
ement); |
| 284 | 291 |
| 285 // 7. Optionally, display a message indicating how the user can exit dis
playing the context object fullscreen. | 292 // 7. Optionally, display a message indicating how the user can exit dis
playing the context object fullscreen. |
| 286 return; | 293 return; |
| 287 } while (0); | 294 } while (0); |
| 288 | 295 |
| 289 enqueueErrorEvent(element); | 296 enqueueErrorEvent(element, requestType); |
| 290 } | 297 } |
| 291 | 298 |
| 292 void FullscreenElementStack::fullyExitFullscreen() | 299 void FullscreenElementStack::fullyExitFullscreen() |
| 293 { | 300 { |
| 294 // "To fully exit fullscreen act as if the exitFullscreen() method was invok
ed on the top-level browsing | 301 // "To fully exit fullscreen act as if the exitFullscreen() method was invok
ed on the top-level browsing |
| 295 // context's document and subsequently empty that document's fullscreen elem
ent stack." | 302 // context's document and subsequently empty that document's fullscreen elem
ent stack." |
| 296 if (!fullscreenElementFrom(document()->topDocument())) | 303 if (!fullscreenElementFrom(document()->topDocument())) |
| 297 return; | 304 return; |
| 298 | 305 |
| 299 // To achieve that aim, remove all the elements from the top document's stac
k except for the first before | 306 // To achieve that aim, remove all the elements from the top document's stac
k except for the first before |
| 300 // calling exitFullscreen(): | 307 // calling exitFullscreen(): |
| 301 WillBeHeapVector<RefPtrWillBeMember<Element> > replacementFullscreenElementS
tack; | 308 WillBeHeapVector<std::pair<RefPtrWillBeMember<Element>, RequestType> > repla
cementFullscreenElementStack; |
| 302 replacementFullscreenElementStack.append(fullscreenElementFrom(document()->t
opDocument())); | |
| 303 FullscreenElementStack& topFullscreenElementStack = from(document()->topDocu
ment()); | 309 FullscreenElementStack& topFullscreenElementStack = from(document()->topDocu
ment()); |
| 310 replacementFullscreenElementStack.append(topFullscreenElementStack.m_fullScr
eenElementStack.last()); |
| 304 topFullscreenElementStack.m_fullScreenElementStack.swap(replacementFullscree
nElementStack); | 311 topFullscreenElementStack.m_fullScreenElementStack.swap(replacementFullscree
nElementStack); |
| 305 topFullscreenElementStack.exitFullscreen(); | 312 topFullscreenElementStack.exitFullscreen(); |
| 306 } | 313 } |
| 307 | 314 |
| 308 void FullscreenElementStack::exitFullscreen() | 315 void FullscreenElementStack::exitFullscreen() |
| 309 { | 316 { |
| 310 // The exitFullscreen() method must run these steps: | 317 // The exitFullscreen() method must run these steps: |
| 311 | 318 |
| 312 // 1. Let doc be the context object. (i.e. "this") | 319 // 1. Let doc be the context object. (i.e. "this") |
| 313 Document* currentDoc = document(); | 320 Document* currentDoc = document(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 327 continue; | 334 continue; |
| 328 ASSERT(toLocalFrame(descendant)->document()); | 335 ASSERT(toLocalFrame(descendant)->document()); |
| 329 if (fullscreenElementFrom(*toLocalFrame(descendant)->document())) | 336 if (fullscreenElementFrom(*toLocalFrame(descendant)->document())) |
| 330 descendants.prepend(toLocalFrame(descendant)->document()); | 337 descendants.prepend(toLocalFrame(descendant)->document()); |
| 331 } | 338 } |
| 332 | 339 |
| 333 // 4. For each descendant in descendants, empty descendant's fullscreen elem
ent stack, and queue a | 340 // 4. For each descendant in descendants, empty descendant's fullscreen elem
ent stack, and queue a |
| 334 // task to fire an event named fullscreenchange with its bubbles attribute s
et to true on descendant. | 341 // task to fire an event named fullscreenchange with its bubbles attribute s
et to true on descendant. |
| 335 for (WillBeHeapDeque<RefPtrWillBeMember<Document> >::iterator i = descendant
s.begin(); i != descendants.end(); ++i) { | 342 for (WillBeHeapDeque<RefPtrWillBeMember<Document> >::iterator i = descendant
s.begin(); i != descendants.end(); ++i) { |
| 336 ASSERT(*i); | 343 ASSERT(*i); |
| 344 RequestType requestType = from(**i).m_fullScreenElementStack.last().seco
nd; |
| 337 from(**i).clearFullscreenElementStack(); | 345 from(**i).clearFullscreenElementStack(); |
| 338 enqueueChangeEvent(**i); | 346 enqueueChangeEvent(**i, requestType); |
| 339 } | 347 } |
| 340 | 348 |
| 341 // 5. While doc is not null, run these substeps: | 349 // 5. While doc is not null, run these substeps: |
| 342 Element* newTop = 0; | 350 Element* newTop = 0; |
| 343 while (currentDoc) { | 351 while (currentDoc) { |
| 352 RequestType requestType = from(*currentDoc).m_fullScreenElementStack.las
t().second; |
| 353 |
| 344 // 1. Pop the top element of doc's fullscreen element stack. | 354 // 1. Pop the top element of doc's fullscreen element stack. |
| 345 from(*currentDoc).popFullscreenElementStack(); | 355 from(*currentDoc).popFullscreenElementStack(); |
| 346 | 356 |
| 347 // If doc's fullscreen element stack is non-empty and the element now
at the top is either | 357 // If doc's fullscreen element stack is non-empty and the element now
at the top is either |
| 348 // not in a document or its node document is not doc, repeat this sub
step. | 358 // not in a document or its node document is not doc, repeat this sub
step. |
| 349 newTop = fullscreenElementFrom(*currentDoc); | 359 newTop = fullscreenElementFrom(*currentDoc); |
| 350 if (newTop && (!newTop->inDocument() || newTop->document() != currentDoc
)) | 360 if (newTop && (!newTop->inDocument() || newTop->document() != currentDoc
)) |
| 351 continue; | 361 continue; |
| 352 | 362 |
| 353 // 2. Queue a task to fire an event named fullscreenchange with its bubb
les attribute set to true | 363 // 2. Queue a task to fire an event named fullscreenchange with its bubb
les attribute set to true |
| 354 // on doc. | 364 // on doc. |
| 355 enqueueChangeEvent(*currentDoc); | 365 enqueueChangeEvent(*currentDoc, requestType); |
| 356 | 366 |
| 357 // 3. If doc's fullscreen element stack is empty and doc's browsing cont
ext has a browsing context | 367 // 3. If doc's fullscreen element stack is empty and doc's browsing cont
ext has a browsing context |
| 358 // container, set doc to that browsing context container's node document
. | 368 // container, set doc to that browsing context container's node document
. |
| 359 if (!newTop && currentDoc->ownerElement()) { | 369 if (!newTop && currentDoc->ownerElement()) { |
| 360 currentDoc = ¤tDoc->ownerElement()->document(); | 370 currentDoc = ¤tDoc->ownerElement()->document(); |
| 361 continue; | 371 continue; |
| 362 } | 372 } |
| 363 | 373 |
| 364 // 4. Otherwise, set doc to null. | 374 // 4. Otherwise, set doc to null. |
| 365 currentDoc = 0; | 375 currentDoc = 0; |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 ASSERT(!m_fullScreenRenderer); | 507 ASSERT(!m_fullScreenRenderer); |
| 498 | 508 |
| 499 m_fullScreenRenderer = renderer; | 509 m_fullScreenRenderer = renderer; |
| 500 } | 510 } |
| 501 | 511 |
| 502 void FullscreenElementStack::fullScreenRendererDestroyed() | 512 void FullscreenElementStack::fullScreenRendererDestroyed() |
| 503 { | 513 { |
| 504 m_fullScreenRenderer = nullptr; | 514 m_fullScreenRenderer = nullptr; |
| 505 } | 515 } |
| 506 | 516 |
| 507 void FullscreenElementStack::enqueueChangeEvent(Document& document) | 517 void FullscreenElementStack::enqueueChangeEvent(Document& document, RequestType
requestType) |
| 508 { | 518 { |
| 509 ASSERT(document.hasFullscreenElementStack()); | 519 RefPtrWillBeRawPtr<Event> event; |
| 510 FullscreenElementStack& fullscreen = from(document); | 520 if (requestType == UnprefixedRequest) { |
| 511 | 521 event = createEvent(EventTypeNames::fullscreenchange, document); |
| 512 EventTarget* target = fullscreen.fullscreenElement(); | 522 } else { |
| 513 if (!target) | 523 ASSERT(document.hasFullscreenElementStack()); |
| 514 target = fullscreen.webkitCurrentFullScreenElement(); | 524 FullscreenElementStack& fullscreen = from(document); |
| 515 if (!target) | 525 EventTarget* target = fullscreen.fullscreenElement(); |
| 516 target = &document; | 526 if (!target) |
| 517 m_eventQueue.append(createEvent(EventTypeNames::webkitfullscreenchange, *tar
get)); | 527 target = fullscreen.webkitCurrentFullScreenElement(); |
| 528 if (!target) |
| 529 target = &document; |
| 530 event = createEvent(EventTypeNames::webkitfullscreenchange, *target); |
| 531 } |
| 532 m_eventQueue.append(event); |
| 518 // NOTE: The timer is started in didEnterFullScreenForElement/didExitFullScr
eenForElement. | 533 // NOTE: The timer is started in didEnterFullScreenForElement/didExitFullScr
eenForElement. |
| 519 } | 534 } |
| 520 | 535 |
| 521 void FullscreenElementStack::enqueueErrorEvent(Element& element) | 536 void FullscreenElementStack::enqueueErrorEvent(Element& element, RequestType req
uestType) |
| 522 { | 537 { |
| 523 m_eventQueue.append(createEvent(EventTypeNames::webkitfullscreenerror, eleme
nt)); | 538 RefPtrWillBeRawPtr<Event> event; |
| 539 if (requestType == UnprefixedRequest) |
| 540 event = createEvent(EventTypeNames::fullscreenerror, element.document())
; |
| 541 else |
| 542 event = createEvent(EventTypeNames::webkitfullscreenerror, element); |
| 543 m_eventQueue.append(event); |
| 524 m_eventQueueTimer.startOneShot(0, FROM_HERE); | 544 m_eventQueueTimer.startOneShot(0, FROM_HERE); |
| 525 } | 545 } |
| 526 | 546 |
| 527 void FullscreenElementStack::eventQueueTimerFired(Timer<FullscreenElementStack>*
) | 547 void FullscreenElementStack::eventQueueTimerFired(Timer<FullscreenElementStack>*
) |
| 528 { | 548 { |
| 529 // Since we dispatch events in this function, it's possible that the | 549 // Since we dispatch events in this function, it's possible that the |
| 530 // document will be detached and GC'd. We protect it here to make sure we | 550 // document will be detached and GC'd. We protect it here to make sure we |
| 531 // can finish the function successfully. | 551 // can finish the function successfully. |
| 532 RefPtrWillBeRawPtr<Document> protectDocument(document()); | 552 RefPtrWillBeRawPtr<Document> protectDocument(document()); |
| 533 WillBeHeapDeque<RefPtrWillBeMember<Event> > eventQueue; | 553 WillBeHeapDeque<RefPtrWillBeMember<Event> > eventQueue; |
| 534 m_eventQueue.swap(eventQueue); | 554 m_eventQueue.swap(eventQueue); |
| 535 | 555 |
| 536 while (!eventQueue.isEmpty()) { | 556 while (!eventQueue.isEmpty()) { |
| 537 RefPtrWillBeRawPtr<Event> event = eventQueue.takeFirst(); | 557 RefPtrWillBeRawPtr<Event> event = eventQueue.takeFirst(); |
| 538 Node* target = event->target()->toNode(); | 558 Node* target = event->target()->toNode(); |
| 539 | 559 |
| 540 // If the element was removed from our tree, also message the documentEl
ement. | 560 // If the element was removed from our tree, also message the documentEl
ement. |
| 541 if (!target->inDocument() && document()->documentElement()) | 561 if (!target->inDocument() && document()->documentElement()) { |
| 562 ASSERT(isPrefixed(event->type())); |
| 542 eventQueue.append(createEvent(event->type(), *document()->documentEl
ement())); | 563 eventQueue.append(createEvent(event->type(), *document()->documentEl
ement())); |
| 564 } |
| 543 | 565 |
| 544 target->dispatchEvent(event); | 566 target->dispatchEvent(event); |
| 545 } | 567 } |
| 546 } | 568 } |
| 547 | 569 |
| 548 void FullscreenElementStack::fullScreenElementRemoved() | 570 void FullscreenElementStack::fullScreenElementRemoved() |
| 549 { | 571 { |
| 550 m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBou
ndaries(false); | 572 m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBou
ndaries(false); |
| 551 fullyExitFullscreen(); | 573 fullyExitFullscreen(); |
| 552 } | 574 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 576 } | 598 } |
| 577 | 599 |
| 578 void FullscreenElementStack::popFullscreenElementStack() | 600 void FullscreenElementStack::popFullscreenElementStack() |
| 579 { | 601 { |
| 580 if (m_fullScreenElementStack.isEmpty()) | 602 if (m_fullScreenElementStack.isEmpty()) |
| 581 return; | 603 return; |
| 582 | 604 |
| 583 m_fullScreenElementStack.removeLast(); | 605 m_fullScreenElementStack.removeLast(); |
| 584 } | 606 } |
| 585 | 607 |
| 586 void FullscreenElementStack::pushFullscreenElementStack(Element& element) | 608 void FullscreenElementStack::pushFullscreenElementStack(Element& element, Reques
tType requestType) |
| 587 { | 609 { |
| 588 m_fullScreenElementStack.append(&element); | 610 m_fullScreenElementStack.append(std::make_pair(&element, requestType)); |
| 589 } | 611 } |
| 590 | 612 |
| 591 void FullscreenElementStack::trace(Visitor* visitor) | 613 void FullscreenElementStack::trace(Visitor* visitor) |
| 592 { | 614 { |
| 593 visitor->trace(m_fullScreenElement); | 615 visitor->trace(m_fullScreenElement); |
| 594 visitor->trace(m_fullScreenElementStack); | 616 visitor->trace(m_fullScreenElementStack); |
| 595 visitor->trace(m_fullScreenRenderer); | 617 visitor->trace(m_fullScreenRenderer); |
| 596 visitor->trace(m_eventQueue); | 618 visitor->trace(m_eventQueue); |
| 597 DocumentSupplement::trace(visitor); | 619 DocumentSupplement::trace(visitor); |
| 598 } | 620 } |
| 599 | 621 |
| 600 } // namespace blink | 622 } // namespace blink |
| OLD | NEW |