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 |