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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
50 if (!isHTMLIFrameElement(owner)) | 50 if (!isHTMLIFrameElement(owner)) |
51 return false; | 51 return false; |
52 if (!owner->hasAttribute(allowfullscreenAttr)) | 52 if (!owner->hasAttribute(allowfullscreenAttr)) |
53 return false; | 53 return false; |
54 } | 54 } |
55 return true; | 55 return true; |
56 } | 56 } |
57 | 57 |
58 static PassRefPtrWillBeRawPtr<Event> createEvent(const AtomicString& type, Event Target& target) | 58 static PassRefPtrWillBeRawPtr<Event> createEvent(const AtomicString& type, Event Target& target) |
59 { | 59 { |
60 RefPtrWillBeRawPtr<Event> event = Event::createBubble(type); | 60 EventInit initializer; |
61 // The prefixed events bubble, the unprefixed ones do not. | |
falken
2014/07/17 03:45:02
I'm probably missing something... why the behavior
| |
62 initializer.bubbles = type == EventTypeNames::webkitfullscreenchange || type == EventTypeNames::webkitfullscreenerror; | |
63 RefPtrWillBeRawPtr<Event> event = Event::create(type, initializer); | |
61 event->setTarget(&target); | 64 event->setTarget(&target); |
62 return event; | 65 return event; |
63 } | 66 } |
64 | 67 |
65 const char* FullscreenElementStack::supplementName() | 68 const char* FullscreenElementStack::supplementName() |
66 { | 69 { |
67 return "FullscreenElementStack"; | 70 return "FullscreenElementStack"; |
68 } | 71 } |
69 | 72 |
70 FullscreenElementStack& FullscreenElementStack::from(Document& document) | 73 FullscreenElementStack& FullscreenElementStack::from(Document& document) |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
228 | 231 |
229 // 1. Let following document be the document after document in docs, or null if there is no | 232 // 1. Let following document be the document after document in docs, or null if there is no |
230 // such document. | 233 // such document. |
231 Document* currentDoc = *current; | 234 Document* currentDoc = *current; |
232 Document* followingDoc = following != docs.end() ? *following : 0; | 235 Document* followingDoc = following != docs.end() ? *following : 0; |
233 | 236 |
234 // 2. If following document is null, push context object on document 's fullscreen element | 237 // 2. If following document is null, push context object on document 's fullscreen element |
235 // stack, and queue a task to fire an event named fullscreenchange w ith its bubbles attribute | 238 // stack, and queue a task to fire an event named fullscreenchange w ith its bubbles attribute |
236 // set to true on the document. | 239 // set to true on the document. |
237 if (!followingDoc) { | 240 if (!followingDoc) { |
238 from(*currentDoc).pushFullscreenElementStack(element); | 241 from(*currentDoc).pushFullscreenElementStack(element, requestTyp e); |
239 enqueueChangeEvent(*currentDoc); | 242 enqueueChangeEvent(*currentDoc, requestType); |
240 continue; | 243 continue; |
241 } | 244 } |
242 | 245 |
243 // 3. Otherwise, if document's fullscreen element stack is either em pty or its top element | 246 // 3. Otherwise, if document's fullscreen element stack is either em pty or its top element |
244 // is not following document's browsing context container, | 247 // is not following document's browsing context container, |
245 Element* topElement = fullscreenElementFrom(*currentDoc); | 248 Element* topElement = fullscreenElementFrom(*currentDoc); |
246 if (!topElement || topElement != followingDoc->ownerElement()) { | 249 if (!topElement || topElement != followingDoc->ownerElement()) { |
247 // ...push following document's browsing context container on do cument's fullscreen element | 250 // ...push following document's browsing context container on do cument's fullscreen element |
248 // stack, and queue a task to fire an event named fullscreenchan ge with its bubbles attribute | 251 // stack, and queue a task to fire an event named fullscreenchan ge with its bubbles attribute |
249 // set to true on document. | 252 // set to true on document. |
250 from(*currentDoc).pushFullscreenElementStack(*followingDoc->owne rElement()); | 253 from(*currentDoc).pushFullscreenElementStack(*followingDoc->owne rElement(), requestType); |
251 enqueueChangeEvent(*currentDoc); | 254 enqueueChangeEvent(*currentDoc, requestType); |
252 continue; | 255 continue; |
253 } | 256 } |
254 | 257 |
255 // 4. Otherwise, do nothing for this document. It stays the same. | 258 // 4. Otherwise, do nothing for this document. It stays the same. |
256 } while (++current != docs.end()); | 259 } while (++current != docs.end()); |
257 | 260 |
258 // 5. Return, and run the remaining steps asynchronously. | 261 // 5. Return, and run the remaining steps asynchronously. |
259 // 6. Optionally, perform some animation. | 262 // 6. Optionally, perform some animation. |
260 m_areKeysEnabledInFullScreen = requestType != PrefixedMozillaRequest && requestType != PrefixedVideoRequest; | 263 m_areKeysEnabledInFullScreen = requestType != PrefixedMozillaRequest && requestType != PrefixedVideoRequest; |
261 document()->frameHost()->chrome().client().enterFullScreenForElement(&el ement); | 264 document()->frameHost()->chrome().client().enterFullScreenForElement(&el ement); |
262 | 265 |
263 // 7. Optionally, display a message indicating how the user can exit dis playing the context object fullscreen. | 266 // 7. Optionally, display a message indicating how the user can exit dis playing the context object fullscreen. |
264 return; | 267 return; |
265 } while (0); | 268 } while (0); |
266 | 269 |
267 enqueueErrorEvent(element); | 270 enqueueErrorEvent(element, requestType); |
268 } | 271 } |
269 | 272 |
270 void FullscreenElementStack::fullyExitFullscreen() | 273 void FullscreenElementStack::fullyExitFullscreen() |
271 { | 274 { |
272 // "To fully exit fullscreen act as if the exitFullscreen() method was invok ed on the top-level browsing | 275 // "To fully exit fullscreen act as if the exitFullscreen() method was invok ed on the top-level browsing |
273 // context's document and subsequently empty that document's fullscreen elem ent stack." | 276 // context's document and subsequently empty that document's fullscreen elem ent stack." |
274 if (!fullscreenElementFrom(document()->topDocument())) | 277 if (!fullscreenElementFrom(document()->topDocument())) |
275 return; | 278 return; |
276 | 279 |
277 // To achieve that aim, remove all the elements from the top document's stac k except for the first before | 280 // To achieve that aim, remove all the elements from the top document's stac k except for the first before |
278 // calling exitFullscreen(): | 281 // calling exitFullscreen(): |
279 WillBeHeapVector<RefPtrWillBeMember<Element> > replacementFullscreenElementS tack; | 282 WillBeHeapVector<std::pair<RefPtrWillBeMember<Element>, RequestType> > repla cementFullscreenElementStack; |
280 replacementFullscreenElementStack.append(fullscreenElementFrom(document()->t opDocument())); | |
281 FullscreenElementStack& topFullscreenElementStack = from(document()->topDocu ment()); | 283 FullscreenElementStack& topFullscreenElementStack = from(document()->topDocu ment()); |
284 replacementFullscreenElementStack.append(topFullscreenElementStack.m_fullScr eenElementStack.last()); | |
282 topFullscreenElementStack.m_fullScreenElementStack.swap(replacementFullscree nElementStack); | 285 topFullscreenElementStack.m_fullScreenElementStack.swap(replacementFullscree nElementStack); |
283 topFullscreenElementStack.exitFullscreen(); | 286 topFullscreenElementStack.exitFullscreen(); |
284 } | 287 } |
285 | 288 |
286 void FullscreenElementStack::exitFullscreen() | 289 void FullscreenElementStack::exitFullscreen() |
287 { | 290 { |
288 // The exitFullscreen() method must run these steps: | 291 // The exitFullscreen() method must run these steps: |
289 | 292 |
290 // 1. Let doc be the context object. (i.e. "this") | 293 // 1. Let doc be the context object. (i.e. "this") |
291 Document* currentDoc = document(); | 294 Document* currentDoc = document(); |
(...skipping 13 matching lines...) Expand all Loading... | |
305 continue; | 308 continue; |
306 ASSERT(toLocalFrame(descendant)->document()); | 309 ASSERT(toLocalFrame(descendant)->document()); |
307 if (fullscreenElementFrom(*toLocalFrame(descendant)->document())) | 310 if (fullscreenElementFrom(*toLocalFrame(descendant)->document())) |
308 descendants.prepend(toLocalFrame(descendant)->document()); | 311 descendants.prepend(toLocalFrame(descendant)->document()); |
309 } | 312 } |
310 | 313 |
311 // 4. For each descendant in descendants, empty descendant's fullscreen elem ent stack, and queue a | 314 // 4. For each descendant in descendants, empty descendant's fullscreen elem ent stack, and queue a |
312 // task to fire an event named fullscreenchange with its bubbles attribute s et to true on descendant. | 315 // task to fire an event named fullscreenchange with its bubbles attribute s et to true on descendant. |
313 for (WillBeHeapDeque<RefPtrWillBeMember<Document> >::iterator i = descendant s.begin(); i != descendants.end(); ++i) { | 316 for (WillBeHeapDeque<RefPtrWillBeMember<Document> >::iterator i = descendant s.begin(); i != descendants.end(); ++i) { |
314 ASSERT(*i); | 317 ASSERT(*i); |
318 RequestType requestType = from(**i).m_fullScreenElementStack.last().seco nd; | |
315 from(**i).clearFullscreenElementStack(); | 319 from(**i).clearFullscreenElementStack(); |
316 enqueueChangeEvent(**i); | 320 enqueueChangeEvent(**i, requestType); |
317 } | 321 } |
318 | 322 |
319 // 5. While doc is not null, run these substeps: | 323 // 5. While doc is not null, run these substeps: |
320 Element* newTop = 0; | 324 Element* newTop = 0; |
321 while (currentDoc) { | 325 while (currentDoc) { |
326 RequestType requestType = from(*currentDoc).m_fullScreenElementStack.las t().second; | |
327 | |
322 // 1. Pop the top element of doc's fullscreen element stack. | 328 // 1. Pop the top element of doc's fullscreen element stack. |
323 from(*currentDoc).popFullscreenElementStack(); | 329 from(*currentDoc).popFullscreenElementStack(); |
324 | 330 |
325 // If doc's fullscreen element stack is non-empty and the element now at the top is either | 331 // If doc's fullscreen element stack is non-empty and the element now at the top is either |
326 // not in a document or its node document is not doc, repeat this sub step. | 332 // not in a document or its node document is not doc, repeat this sub step. |
327 newTop = fullscreenElementFrom(*currentDoc); | 333 newTop = fullscreenElementFrom(*currentDoc); |
328 if (newTop && (!newTop->inDocument() || newTop->document() != currentDoc )) | 334 if (newTop && (!newTop->inDocument() || newTop->document() != currentDoc )) |
329 continue; | 335 continue; |
330 | 336 |
331 // 2. Queue a task to fire an event named fullscreenchange with its bubb les attribute set to true | 337 // 2. Queue a task to fire an event named fullscreenchange with its bubb les attribute set to true |
332 // on doc. | 338 // on doc. |
333 enqueueChangeEvent(*currentDoc); | 339 enqueueChangeEvent(*currentDoc, requestType); |
334 | 340 |
335 // 3. If doc's fullscreen element stack is empty and doc's browsing cont ext has a browsing context | 341 // 3. If doc's fullscreen element stack is empty and doc's browsing cont ext has a browsing context |
336 // container, set doc to that browsing context container's node document . | 342 // container, set doc to that browsing context container's node document . |
337 if (!newTop && currentDoc->ownerElement()) { | 343 if (!newTop && currentDoc->ownerElement()) { |
338 currentDoc = ¤tDoc->ownerElement()->document(); | 344 currentDoc = ¤tDoc->ownerElement()->document(); |
339 continue; | 345 continue; |
340 } | 346 } |
341 | 347 |
342 // 4. Otherwise, set doc to null. | 348 // 4. Otherwise, set doc to null. |
343 currentDoc = 0; | 349 currentDoc = 0; |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
475 ASSERT(!m_fullScreenRenderer); | 481 ASSERT(!m_fullScreenRenderer); |
476 | 482 |
477 m_fullScreenRenderer = renderer; | 483 m_fullScreenRenderer = renderer; |
478 } | 484 } |
479 | 485 |
480 void FullscreenElementStack::fullScreenRendererDestroyed() | 486 void FullscreenElementStack::fullScreenRendererDestroyed() |
481 { | 487 { |
482 m_fullScreenRenderer = 0; | 488 m_fullScreenRenderer = 0; |
483 } | 489 } |
484 | 490 |
485 void FullscreenElementStack::enqueueChangeEvent(Document& document) | 491 void FullscreenElementStack::enqueueChangeEvent(Document& document, RequestType requestType) |
486 { | 492 { |
487 ASSERT(document.hasFullscreenElementStack()); | 493 RefPtrWillBeRawPtr<Event> event; |
488 FullscreenElementStack& fullscreen = from(document); | 494 if (requestType == UnprefixedRequest) { |
489 | 495 event = createEvent(EventTypeNames::fullscreenchange, document); |
falken
2014/07/17 03:45:02
Why is the target different between unprefixed and
| |
490 EventTarget* target = fullscreen.fullscreenElement(); | 496 } else { |
491 if (!target) | 497 ASSERT(document.hasFullscreenElementStack()); |
492 target = fullscreen.webkitCurrentFullScreenElement(); | 498 FullscreenElementStack& fullscreen = from(document); |
493 if (!target) | 499 EventTarget* target = fullscreen.fullscreenElement(); |
494 target = &document; | 500 if (!target) |
495 m_eventQueue.append(createEvent(EventTypeNames::webkitfullscreenchange, *tar get)); | 501 target = fullscreen.webkitCurrentFullScreenElement(); |
502 if (!target) | |
503 target = &document; | |
504 event = createEvent(EventTypeNames::webkitfullscreenchange, *target); | |
505 } | |
506 m_eventQueue.append(event); | |
496 // NOTE: The timer is started in didEnterFullScreenForElement/didExitFullScr eenForElement. | 507 // NOTE: The timer is started in didEnterFullScreenForElement/didExitFullScr eenForElement. |
497 } | 508 } |
498 | 509 |
499 void FullscreenElementStack::enqueueErrorEvent(Element& element) | 510 void FullscreenElementStack::enqueueErrorEvent(Element& element, RequestType req uestType) |
500 { | 511 { |
501 m_eventQueue.append(createEvent(EventTypeNames::webkitfullscreenerror, eleme nt)); | 512 RefPtrWillBeRawPtr<Event> event; |
513 if (requestType == UnprefixedRequest) | |
514 event = createEvent(EventTypeNames::fullscreenerror, element.document()) ; | |
515 else | |
516 event = createEvent(EventTypeNames::webkitfullscreenerror, element); | |
517 m_eventQueue.append(event); | |
502 m_eventQueueTimer.startOneShot(0, FROM_HERE); | 518 m_eventQueueTimer.startOneShot(0, FROM_HERE); |
503 } | 519 } |
504 | 520 |
505 void FullscreenElementStack::eventQueueTimerFired(Timer<FullscreenElementStack>* ) | 521 void FullscreenElementStack::eventQueueTimerFired(Timer<FullscreenElementStack>* ) |
506 { | 522 { |
507 // Since we dispatch events in this function, it's possible that the | 523 // Since we dispatch events in this function, it's possible that the |
508 // document will be detached and GC'd. We protect it here to make sure we | 524 // document will be detached and GC'd. We protect it here to make sure we |
509 // can finish the function successfully. | 525 // can finish the function successfully. |
510 RefPtrWillBeRawPtr<Document> protectDocument(document()); | 526 RefPtrWillBeRawPtr<Document> protectDocument(document()); |
511 WillBeHeapDeque<RefPtrWillBeMember<Event> > eventQueue; | 527 WillBeHeapDeque<RefPtrWillBeMember<Event> > eventQueue; |
512 m_eventQueue.swap(eventQueue); | 528 m_eventQueue.swap(eventQueue); |
513 | 529 |
514 while (!eventQueue.isEmpty()) { | 530 while (!eventQueue.isEmpty()) { |
515 RefPtrWillBeRawPtr<Event> event = eventQueue.takeFirst(); | 531 RefPtrWillBeRawPtr<Event> event = eventQueue.takeFirst(); |
516 Node* target = event->target()->toNode(); | 532 Node* target = event->target()->toNode(); |
517 | 533 |
518 // If the element was removed from our tree, also message the documentEl ement. | 534 // If the element was removed from our tree, also message the documentEl ement. |
519 if (!target->inDocument() && document()->documentElement()) | 535 if (!target->inDocument() && document()->documentElement()) { |
536 ASSERT(event->type() == EventTypeNames::webkitfullscreenchange || ev ent->type() == EventTypeNames::webkitfullscreenerror); | |
520 eventQueue.append(createEvent(event->type(), *document()->documentEl ement())); | 537 eventQueue.append(createEvent(event->type(), *document()->documentEl ement())); |
538 } | |
521 | 539 |
522 target->dispatchEvent(event); | 540 target->dispatchEvent(event); |
523 } | 541 } |
524 } | 542 } |
525 | 543 |
526 void FullscreenElementStack::fullScreenElementRemoved() | 544 void FullscreenElementStack::fullScreenElementRemoved() |
527 { | 545 { |
528 m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBou ndaries(false); | 546 m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBou ndaries(false); |
529 fullyExitFullscreen(); | 547 fullyExitFullscreen(); |
530 } | 548 } |
(...skipping 23 matching lines...) Expand all Loading... | |
554 } | 572 } |
555 | 573 |
556 void FullscreenElementStack::popFullscreenElementStack() | 574 void FullscreenElementStack::popFullscreenElementStack() |
557 { | 575 { |
558 if (m_fullScreenElementStack.isEmpty()) | 576 if (m_fullScreenElementStack.isEmpty()) |
559 return; | 577 return; |
560 | 578 |
561 m_fullScreenElementStack.removeLast(); | 579 m_fullScreenElementStack.removeLast(); |
562 } | 580 } |
563 | 581 |
564 void FullscreenElementStack::pushFullscreenElementStack(Element& element) | 582 void FullscreenElementStack::pushFullscreenElementStack(Element& element, Reques tType requestType) |
565 { | 583 { |
566 m_fullScreenElementStack.append(&element); | 584 m_fullScreenElementStack.append(std::make_pair(&element, requestType)); |
567 } | 585 } |
568 | 586 |
569 void FullscreenElementStack::trace(Visitor* visitor) | 587 void FullscreenElementStack::trace(Visitor* visitor) |
570 { | 588 { |
571 visitor->trace(m_fullScreenElement); | 589 visitor->trace(m_fullScreenElement); |
572 visitor->trace(m_fullScreenElementStack); | 590 visitor->trace(m_fullScreenElementStack); |
573 visitor->trace(m_eventQueue); | 591 visitor->trace(m_eventQueue); |
574 DocumentSupplement::trace(visitor); | 592 DocumentSupplement::trace(visitor); |
575 } | 593 } |
576 | 594 |
577 } // namespace WebCore | 595 } // namespace WebCore |
OLD | NEW |