Chromium Code Reviews| 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 |