| 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 |
| 7 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) | 7 * rights reserved. |
| 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. |
| 9 * (http://www.torchmobile.com/) |
| 8 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) | 10 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) |
| 9 * Copyright (C) 2013 Google Inc. All rights reserved. | 11 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 10 * | 12 * |
| 11 * This library is free software; you can redistribute it and/or | 13 * This library is free software; you can redistribute it and/or |
| 12 * modify it under the terms of the GNU Library General Public | 14 * modify it under the terms of the GNU Library General Public |
| 13 * License as published by the Free Software Foundation; either | 15 * License as published by the Free Software Foundation; either |
| 14 * version 2 of the License, or (at your option) any later version. | 16 * version 2 of the License, or (at your option) any later version. |
| 15 * | 17 * |
| 16 * This library is distributed in the hope that it will be useful, | 18 * This library is distributed in the hope that it will be useful, |
| 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 "requestFullscreen", "Element", | 93 "requestFullscreen", "Element", |
| 92 "API can only be initiated by a user gesture."); | 94 "API can only be initiated by a user gesture."); |
| 93 document.addConsoleMessage( | 95 document.addConsoleMessage( |
| 94 ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message)); | 96 ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message)); |
| 95 | 97 |
| 96 return false; | 98 return false; |
| 97 } | 99 } |
| 98 | 100 |
| 99 // https://fullscreen.spec.whatwg.org/#fullscreen-is-supported | 101 // https://fullscreen.spec.whatwg.org/#fullscreen-is-supported |
| 100 bool fullscreenIsSupported(const Document& document) { | 102 bool fullscreenIsSupported(const Document& document) { |
| 101 // Fullscreen is supported if there is no previously-established user preferen
ce, | 103 // Fullscreen is supported if there is no previously-established user |
| 102 // security risk, or platform limitation. | 104 // preference, security risk, or platform limitation. |
| 103 return !document.settings() || document.settings()->fullscreenSupported(); | 105 return !document.settings() || document.settings()->fullscreenSupported(); |
| 104 } | 106 } |
| 105 | 107 |
| 106 // https://fullscreen.spec.whatwg.org/#fullscreen-element-ready-check | 108 // https://fullscreen.spec.whatwg.org/#fullscreen-element-ready-check |
| 107 bool fullscreenElementReady(const Element& element) { | 109 bool fullscreenElementReady(const Element& element) { |
| 108 // A fullscreen element ready check for an element |element| returns true if a
ll of the | 110 // A fullscreen element ready check for an element |element| returns true if |
| 109 // following are true, and false otherwise: | 111 // all of the following are true, and false otherwise: |
| 110 | 112 |
| 111 // |element| is in a document. | 113 // |element| is in a document. |
| 112 if (!element.isConnected()) | 114 if (!element.isConnected()) |
| 113 return false; | 115 return false; |
| 114 | 116 |
| 115 // |element|'s node document is allowed to use the feature indicated by | 117 // |element|'s node document is allowed to use the feature indicated by |
| 116 // attribute name allowfullscreen. | 118 // attribute name allowfullscreen. |
| 117 if (!allowedToUseFullscreen(element.document().frame())) | 119 if (!allowedToUseFullscreen(element.document().frame())) |
| 118 return false; | 120 return false; |
| 119 | 121 |
| 120 // |element|'s node document's fullscreen element stack is either empty or its
top element is an | 122 // |element|'s node document's fullscreen element stack is either empty or its |
| 121 // inclusive ancestor of |element|. | 123 // top element is an inclusive ancestor of |element|. |
| 122 if (const Element* topElement = | 124 if (const Element* topElement = |
| 123 Fullscreen::fullscreenElementFrom(element.document())) { | 125 Fullscreen::fullscreenElementFrom(element.document())) { |
| 124 if (!topElement->contains(&element)) | 126 if (!topElement->contains(&element)) |
| 125 return false; | 127 return false; |
| 126 } | 128 } |
| 127 | 129 |
| 128 // |element| has no ancestor element whose local name is iframe and namespace
is the HTML | 130 // |element| has no ancestor element whose local name is iframe and namespace |
| 129 // namespace. | 131 // is the HTML namespace. |
| 130 if (Traversal<HTMLIFrameElement>::firstAncestor(element)) | 132 if (Traversal<HTMLIFrameElement>::firstAncestor(element)) |
| 131 return false; | 133 return false; |
| 132 | 134 |
| 133 // |element|'s node document's browsing context either has a browsing context
container and the | 135 // |element|'s node document's browsing context either has a browsing context |
| 134 // fullscreen element ready check returns true for |element|'s node document's
browsing | 136 // container and the fullscreen element ready check returns true for |
| 135 // context's browsing context container, or it has no browsing context contain
er. | 137 // |element|'s node document's browsing context's browsing context container, |
| 138 // or it has no browsing context container. |
| 136 if (const Element* owner = element.document().localOwner()) { | 139 if (const Element* owner = element.document().localOwner()) { |
| 137 if (!fullscreenElementReady(*owner)) | 140 if (!fullscreenElementReady(*owner)) |
| 138 return false; | 141 return false; |
| 139 } | 142 } |
| 140 | 143 |
| 141 return true; | 144 return true; |
| 142 } | 145 } |
| 143 | 146 |
| 144 bool isPrefixed(const AtomicString& type) { | 147 bool isPrefixed(const AtomicString& type) { |
| 145 return type == EventTypeNames::webkitfullscreenchange || | 148 return type == EventTypeNames::webkitfullscreenchange || |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 UseCounter::count(document, UseCounter::FullscreenInsecureOrigin); | 257 UseCounter::count(document, UseCounter::FullscreenInsecureOrigin); |
| 255 HostsUsingFeatures::countAnyWorld( | 258 HostsUsingFeatures::countAnyWorld( |
| 256 document, HostsUsingFeatures::Feature::FullscreenInsecureHost); | 259 document, HostsUsingFeatures::Feature::FullscreenInsecureHost); |
| 257 } | 260 } |
| 258 } | 261 } |
| 259 | 262 |
| 260 // Ignore this request if the document is not in a live frame. | 263 // Ignore this request if the document is not in a live frame. |
| 261 if (!document.isActive()) | 264 if (!document.isActive()) |
| 262 return; | 265 return; |
| 263 | 266 |
| 264 // If |element| is on top of |doc|'s fullscreen element stack, terminate these
substeps. | 267 // If |element| is on top of |doc|'s fullscreen element stack, terminate these |
| 268 // substeps. |
| 265 if (&element == fullscreenElementFrom(document)) | 269 if (&element == fullscreenElementFrom(document)) |
| 266 return; | 270 return; |
| 267 | 271 |
| 268 do { | 272 do { |
| 269 // 1. If any of the following conditions are true, terminate these steps and
queue a task to fire | 273 // 1. If any of the following conditions are true, terminate these steps and |
| 270 // an event named fullscreenerror with its bubbles attribute set to true on
the context object's | 274 // queue a task to fire an event named fullscreenerror with its bubbles |
| 271 // node document: | 275 // attribute set to true on the context object's node document: |
| 272 | 276 |
| 273 // The fullscreen element ready check returns false. | 277 // The fullscreen element ready check returns false. |
| 274 if (!fullscreenElementReady(element)) | 278 if (!fullscreenElementReady(element)) |
| 275 break; | 279 break; |
| 276 | 280 |
| 277 // Fullscreen is not supported. | 281 // Fullscreen is not supported. |
| 278 if (!fullscreenIsSupported(document)) | 282 if (!fullscreenIsSupported(document)) |
| 279 break; | 283 break; |
| 280 | 284 |
| 281 // This algorithm is not allowed to request fullscreen. | 285 // This algorithm is not allowed to request fullscreen. |
| 282 // OOPIF: If |forCrossProcessDescendant| is true, requestFullscreen was | 286 // OOPIF: If |forCrossProcessDescendant| is true, requestFullscreen was |
| 283 // already called on a descendant element in another process, and | 287 // already called on a descendant element in another process, and |
| 284 // getting here means that it was already allowed to request fullscreen. | 288 // getting here means that it was already allowed to request fullscreen. |
| 285 if (!forCrossProcessDescendant && !allowedToRequestFullscreen(document)) | 289 if (!forCrossProcessDescendant && !allowedToRequestFullscreen(document)) |
| 286 break; | 290 break; |
| 287 | 291 |
| 288 // 2. Let doc be element's node document. (i.e. "this") | 292 // 2. Let doc be element's node document. (i.e. "this") |
| 289 | 293 |
| 290 // 3. Let docs be all doc's ancestor browsing context's documents (if any) a
nd doc. | 294 // 3. Let docs be all doc's ancestor browsing context's documents (if any) |
| 295 // and doc. |
| 291 // | 296 // |
| 292 // For OOPIF scenarios, |docs| will only contain documents for local | 297 // For OOPIF scenarios, |docs| will only contain documents for local |
| 293 // ancestors, and remote ancestors will be processed in their | 298 // ancestors, and remote ancestors will be processed in their |
| 294 // respective processes. This preserves the spec's event firing order | 299 // respective processes. This preserves the spec's event firing order |
| 295 // for local ancestors, but not for remote ancestors. However, that | 300 // for local ancestors, but not for remote ancestors. However, that |
| 296 // difference shouldn't be observable in practice: a fullscreenchange | 301 // difference shouldn't be observable in practice: a fullscreenchange |
| 297 // event handler would need to postMessage a frame in another renderer | 302 // event handler would need to postMessage a frame in another renderer |
| 298 // process, where the message should be queued up and processed after | 303 // process, where the message should be queued up and processed after |
| 299 // the IPC that dispatches fullscreenchange. | 304 // the IPC that dispatches fullscreenchange. |
| 300 HeapDeque<Member<Document>> docs; | 305 HeapDeque<Member<Document>> docs; |
| 301 | 306 |
| 302 docs.prepend(&document); | 307 docs.prepend(&document); |
| 303 for (Frame* frame = document.frame()->tree().parent(); frame; | 308 for (Frame* frame = document.frame()->tree().parent(); frame; |
| 304 frame = frame->tree().parent()) { | 309 frame = frame->tree().parent()) { |
| 305 if (frame->isLocalFrame()) | 310 if (frame->isLocalFrame()) |
| 306 docs.prepend(toLocalFrame(frame)->document()); | 311 docs.prepend(toLocalFrame(frame)->document()); |
| 307 } | 312 } |
| 308 | 313 |
| 309 // 4. For each document in docs, run these substeps: | 314 // 4. For each document in docs, run these substeps: |
| 310 HeapDeque<Member<Document>>::iterator current = docs.begin(), | 315 HeapDeque<Member<Document>>::iterator current = docs.begin(), |
| 311 following = docs.begin(); | 316 following = docs.begin(); |
| 312 | 317 |
| 313 do { | 318 do { |
| 314 ++following; | 319 ++following; |
| 315 | 320 |
| 316 // 1. Let following document be the document after document in docs, or nu
ll if there is no | 321 // 1. Let following document be the document after document in docs, or |
| 317 // such document. | 322 // null if there is no such document. |
| 318 Document* currentDoc = *current; | 323 Document* currentDoc = *current; |
| 319 Document* followingDoc = following != docs.end() ? *following : nullptr; | 324 Document* followingDoc = following != docs.end() ? *following : nullptr; |
| 320 | 325 |
| 321 // 2. If following document is null, push context object on document's ful
lscreen element | 326 // 2. If following document is null, push context object on document's |
| 322 // stack, and queue a task to fire an event named fullscreenchange with it
s bubbles attribute | 327 // fullscreen element stack, and queue a task to fire an event named |
| 323 // set to true on the document. | 328 // fullscreenchange with its bubbles attribute set to true on the |
| 329 // document. |
| 324 if (!followingDoc) { | 330 if (!followingDoc) { |
| 325 from(*currentDoc).pushFullscreenElementStack(element, requestType); | 331 from(*currentDoc).pushFullscreenElementStack(element, requestType); |
| 326 from(document).enqueueChangeEvent(*currentDoc, requestType); | 332 from(document).enqueueChangeEvent(*currentDoc, requestType); |
| 327 continue; | 333 continue; |
| 328 } | 334 } |
| 329 | 335 |
| 330 // 3. Otherwise, if document's fullscreen element stack is either empty or
its top element | 336 // 3. Otherwise, if document's fullscreen element stack is either empty or |
| 331 // is not following document's browsing context container, | 337 // its top element is not following document's browsing context container, |
| 332 Element* topElement = fullscreenElementFrom(*currentDoc); | 338 Element* topElement = fullscreenElementFrom(*currentDoc); |
| 333 HTMLFrameOwnerElement* followingOwner = | 339 HTMLFrameOwnerElement* followingOwner = |
| 334 findContainerForDescendant(*currentDoc, *followingDoc); | 340 findContainerForDescendant(*currentDoc, *followingDoc); |
| 335 if (!topElement || topElement != followingOwner) { | 341 if (!topElement || topElement != followingOwner) { |
| 336 // ...push following document's browsing context container on document's
fullscreen element | 342 // ...push following document's browsing context container on document's |
| 337 // stack, and queue a task to fire an event named fullscreenchange with
its bubbles attribute | 343 // fullscreen element stack, and queue a task to fire an event named |
| 338 // set to true on document. | 344 // fullscreenchange with its bubbles attribute set to true on document. |
| 339 from(*currentDoc) | 345 from(*currentDoc) |
| 340 .pushFullscreenElementStack(*followingOwner, requestType); | 346 .pushFullscreenElementStack(*followingOwner, requestType); |
| 341 from(document).enqueueChangeEvent(*currentDoc, requestType); | 347 from(document).enqueueChangeEvent(*currentDoc, requestType); |
| 342 continue; | 348 continue; |
| 343 } | 349 } |
| 344 | 350 |
| 345 // 4. Otherwise, do nothing for this document. It stays the same. | 351 // 4. Otherwise, do nothing for this document. It stays the same. |
| 346 } while (++current != docs.end()); | 352 } while (++current != docs.end()); |
| 347 | 353 |
| 348 from(document).m_forCrossProcessDescendant = forCrossProcessDescendant; | 354 from(document).m_forCrossProcessDescendant = forCrossProcessDescendant; |
| 349 | 355 |
| 350 // 5. Return, and run the remaining steps asynchronously. | 356 // 5. Return, and run the remaining steps asynchronously. |
| 351 // 6. Optionally, perform some animation. | 357 // 6. Optionally, perform some animation. |
| 352 document.frameHost()->chromeClient().enterFullscreenForElement(&element); | 358 document.frameHost()->chromeClient().enterFullscreenForElement(&element); |
| 353 | 359 |
| 354 // 7. Optionally, display a message indicating how the user can exit display
ing the context object fullscreen. | 360 // 7. Optionally, display a message indicating how the user can exit |
| 361 // displaying the context object fullscreen. |
| 355 return; | 362 return; |
| 356 } while (false); | 363 } while (false); |
| 357 | 364 |
| 358 from(document).enqueueErrorEvent(element, requestType); | 365 from(document).enqueueErrorEvent(element, requestType); |
| 359 } | 366 } |
| 360 | 367 |
| 361 // https://fullscreen.spec.whatwg.org/#fully-exit-fullscreen | 368 // https://fullscreen.spec.whatwg.org/#fully-exit-fullscreen |
| 362 void Fullscreen::fullyExitFullscreen(Document& document) { | 369 void Fullscreen::fullyExitFullscreen(Document& document) { |
| 363 // To fully exit fullscreen, run these steps: | 370 // To fully exit fullscreen, run these steps: |
| 364 | 371 |
| 365 // 1. Let |doc| be the top-level browsing context's document. | 372 // 1. Let |doc| be the top-level browsing context's document. |
| 366 // | 373 // |
| 367 // Since the top-level browsing context's document might be unavailable in | 374 // Since the top-level browsing context's document might be unavailable in |
| 368 // OOPIF scenarios (i.e., when the top frame is remote), this actually uses | 375 // OOPIF scenarios (i.e., when the top frame is remote), this actually uses |
| 369 // the Document of the topmost local ancestor frame. Without OOPIF, this | 376 // the Document of the topmost local ancestor frame. Without OOPIF, this |
| 370 // will be the top frame's document. With OOPIF, each renderer process for | 377 // will be the top frame's document. With OOPIF, each renderer process for |
| 371 // the current page will separately call fullyExitFullscreen to cover all | 378 // the current page will separately call fullyExitFullscreen to cover all |
| 372 // local frames in each process. | 379 // local frames in each process. |
| 373 Document& doc = topmostLocalAncestor(document); | 380 Document& doc = topmostLocalAncestor(document); |
| 374 | 381 |
| 375 // 2. If |doc|'s fullscreen element stack is empty, terminate these steps. | 382 // 2. If |doc|'s fullscreen element stack is empty, terminate these steps. |
| 376 if (!fullscreenElementFrom(doc)) | 383 if (!fullscreenElementFrom(doc)) |
| 377 return; | 384 return; |
| 378 | 385 |
| 379 // 3. Remove elements from |doc|'s fullscreen element stack until only the top
element is left. | 386 // 3. Remove elements from |doc|'s fullscreen element stack until only the top |
| 387 // element is left. |
| 380 size_t stackSize = from(doc).m_fullscreenElementStack.size(); | 388 size_t stackSize = from(doc).m_fullscreenElementStack.size(); |
| 381 from(doc).m_fullscreenElementStack.remove(0, stackSize - 1); | 389 from(doc).m_fullscreenElementStack.remove(0, stackSize - 1); |
| 382 DCHECK_EQ(from(doc).m_fullscreenElementStack.size(), 1u); | 390 DCHECK_EQ(from(doc).m_fullscreenElementStack.size(), 1u); |
| 383 | 391 |
| 384 // 4. Act as if the exitFullscreen() method was invoked on |doc|. | 392 // 4. Act as if the exitFullscreen() method was invoked on |doc|. |
| 385 exitFullscreen(doc); | 393 exitFullscreen(doc); |
| 386 } | 394 } |
| 387 | 395 |
| 388 // https://fullscreen.spec.whatwg.org/#exit-fullscreen | 396 // https://fullscreen.spec.whatwg.org/#exit-fullscreen |
| 389 void Fullscreen::exitFullscreen(Document& document) { | 397 void Fullscreen::exitFullscreen(Document& document) { |
| 390 // The exitFullscreen() method must run these steps: | 398 // The exitFullscreen() method must run these steps: |
| 391 | 399 |
| 392 // 1. Let doc be the context object. (i.e. "this") | 400 // 1. Let doc be the context object. (i.e. "this") |
| 393 if (!document.isActive()) | 401 if (!document.isActive()) |
| 394 return; | 402 return; |
| 395 | 403 |
| 396 // 2. If doc's fullscreen element stack is empty, terminate these steps. | 404 // 2. If doc's fullscreen element stack is empty, terminate these steps. |
| 397 if (!fullscreenElementFrom(document)) | 405 if (!fullscreenElementFrom(document)) |
| 398 return; | 406 return; |
| 399 | 407 |
| 400 // 3. Let descendants be all the doc's descendant browsing context's documents
with a non-empty fullscreen | 408 // 3. Let descendants be all the doc's descendant browsing context's documents |
| 401 // element stack (if any), ordered so that the child of the doc is last and th
e document furthest | 409 // with a non-empty fullscreen element stack (if any), ordered so that the |
| 402 // away from the doc is first. | 410 // child of the doc is last and the document furthest away from the doc is |
| 411 // first. |
| 403 HeapDeque<Member<Document>> descendants; | 412 HeapDeque<Member<Document>> descendants; |
| 404 for (Frame* descendant = | 413 for (Frame* descendant = |
| 405 document.frame() ? document.frame()->tree().traverseNext() : nullptr; | 414 document.frame() ? document.frame()->tree().traverseNext() : nullptr; |
| 406 descendant; descendant = descendant->tree().traverseNext()) { | 415 descendant; descendant = descendant->tree().traverseNext()) { |
| 407 if (!descendant->isLocalFrame()) | 416 if (!descendant->isLocalFrame()) |
| 408 continue; | 417 continue; |
| 409 DCHECK(toLocalFrame(descendant)->document()); | 418 DCHECK(toLocalFrame(descendant)->document()); |
| 410 if (fullscreenElementFrom(*toLocalFrame(descendant)->document())) | 419 if (fullscreenElementFrom(*toLocalFrame(descendant)->document())) |
| 411 descendants.prepend(toLocalFrame(descendant)->document()); | 420 descendants.prepend(toLocalFrame(descendant)->document()); |
| 412 } | 421 } |
| 413 | 422 |
| 414 // 4. For each descendant in descendants, empty descendant's fullscreen elemen
t stack, and queue a | 423 // 4. For each descendant in descendants, empty descendant's fullscreen |
| 415 // task to fire an event named fullscreenchange with its bubbles attribute set
to true on descendant. | 424 // element stack, and queue a task to fire an event named fullscreenchange |
| 425 // with its bubbles attribute set to true on descendant. |
| 416 for (auto& descendant : descendants) { | 426 for (auto& descendant : descendants) { |
| 417 DCHECK(descendant); | 427 DCHECK(descendant); |
| 418 RequestType requestType = | 428 RequestType requestType = |
| 419 from(*descendant).m_fullscreenElementStack.last().second; | 429 from(*descendant).m_fullscreenElementStack.last().second; |
| 420 from(*descendant).clearFullscreenElementStack(); | 430 from(*descendant).clearFullscreenElementStack(); |
| 421 from(document).enqueueChangeEvent(*descendant, requestType); | 431 from(document).enqueueChangeEvent(*descendant, requestType); |
| 422 } | 432 } |
| 423 | 433 |
| 424 // 5. While doc is not null, run these substeps: | 434 // 5. While doc is not null, run these substeps: |
| 425 Element* newTop = nullptr; | 435 Element* newTop = nullptr; |
| 426 for (Document* currentDoc = &document; currentDoc;) { | 436 for (Document* currentDoc = &document; currentDoc;) { |
| 427 RequestType requestType = | 437 RequestType requestType = |
| 428 from(*currentDoc).m_fullscreenElementStack.last().second; | 438 from(*currentDoc).m_fullscreenElementStack.last().second; |
| 429 | 439 |
| 430 // 1. Pop the top element of doc's fullscreen element stack. | 440 // 1. Pop the top element of doc's fullscreen element stack. |
| 431 from(*currentDoc).popFullscreenElementStack(); | 441 from(*currentDoc).popFullscreenElementStack(); |
| 432 | 442 |
| 433 // If doc's fullscreen element stack is non-empty and the element now at
the top is either | 443 // If doc's fullscreen element stack is non-empty and the element now at |
| 434 // not in a document or its node document is not doc, repeat this substep
. | 444 // the top is either not in a document or its node document is not doc, |
| 445 // repeat this substep. |
| 435 newTop = fullscreenElementFrom(*currentDoc); | 446 newTop = fullscreenElementFrom(*currentDoc); |
| 436 if (newTop && (!newTop->isConnected() || newTop->document() != currentDoc)) | 447 if (newTop && (!newTop->isConnected() || newTop->document() != currentDoc)) |
| 437 continue; | 448 continue; |
| 438 | 449 |
| 439 // 2. Queue a task to fire an event named fullscreenchange with its bubbles
attribute set to true | 450 // 2. Queue a task to fire an event named fullscreenchange with its bubbles |
| 440 // on doc. | 451 // attribute set to true on doc. |
| 441 from(document).enqueueChangeEvent(*currentDoc, requestType); | 452 from(document).enqueueChangeEvent(*currentDoc, requestType); |
| 442 | 453 |
| 443 // 3. If doc's fullscreen element stack is empty and doc's browsing context
has a browsing context | 454 // 3. If doc's fullscreen element stack is empty and doc's browsing context |
| 444 // container, set doc to that browsing context container's node document. | 455 // has a browsing context container, set doc to that browsing context |
| 456 // container's node document. |
| 445 // | 457 // |
| 446 // OOPIF: If browsing context container's document is in another | 458 // OOPIF: If browsing context container's document is in another |
| 447 // process, keep moving up the ancestor chain and looking for a | 459 // process, keep moving up the ancestor chain and looking for a |
| 448 // browsing context container with a local document. | 460 // browsing context container with a local document. |
| 449 // TODO(alexmos): Deal with nested fullscreen cases, see | 461 // TODO(alexmos): Deal with nested fullscreen cases, see |
| 450 // https://crbug.com/617369. | 462 // https://crbug.com/617369. |
| 451 if (!newTop) { | 463 if (!newTop) { |
| 452 Frame* frame = currentDoc->frame()->tree().parent(); | 464 Frame* frame = currentDoc->frame()->tree().parent(); |
| 453 while (frame && frame->isRemoteFrame()) | 465 while (frame && frame->isRemoteFrame()) |
| 454 frame = frame->tree().parent(); | 466 frame = frame->tree().parent(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 466 // 7. Optionally, perform some animation. | 478 // 7. Optionally, perform some animation. |
| 467 | 479 |
| 468 FrameHost* host = document.frameHost(); | 480 FrameHost* host = document.frameHost(); |
| 469 | 481 |
| 470 // Speculative fix for engaget.com/videos per crbug.com/336239. | 482 // Speculative fix for engaget.com/videos per crbug.com/336239. |
| 471 // FIXME: This check is wrong. We DCHECK(document->isActive()) above | 483 // FIXME: This check is wrong. We DCHECK(document->isActive()) above |
| 472 // so this should be redundant and should be removed! | 484 // so this should be redundant and should be removed! |
| 473 if (!host) | 485 if (!host) |
| 474 return; | 486 return; |
| 475 | 487 |
| 476 // Only exit out of full screen window mode if there are no remaining elements
in the | 488 // Only exit out of full screen window mode if there are no remaining elements |
| 477 // full screen stack. | 489 // in the full screen stack. |
| 478 if (!newTop) { | 490 if (!newTop) { |
| 479 // FIXME: if the frame exiting fullscreen is not the frame that entered | 491 // FIXME: if the frame exiting fullscreen is not the frame that entered |
| 480 // fullscreen (but a parent frame for example), | 492 // fullscreen (but a parent frame for example), |
| 481 // m_currentFullScreenElement might be null. We want to pass an element | 493 // m_currentFullScreenElement might be null. We want to pass an element |
| 482 // that is part of the document so we will pass the documentElement in | 494 // that is part of the document so we will pass the documentElement in |
| 483 // that case. This should be fix by exiting fullscreen for a frame | 495 // that case. This should be fix by exiting fullscreen for a frame |
| 484 // instead of an element, see https://crbug.com/441259 | 496 // instead of an element, see https://crbug.com/441259 |
| 485 Element* currentFullScreenElement = currentFullScreenElementFrom(document); | 497 Element* currentFullScreenElement = currentFullScreenElementFrom(document); |
| 486 host->chromeClient().exitFullscreenForElement( | 498 host->chromeClient().exitFullscreenForElement( |
| 487 currentFullScreenElement ? currentFullScreenElement | 499 currentFullScreenElement ? currentFullScreenElement |
| (...skipping 17 matching lines...) Expand all Loading... |
| 505 void Fullscreen::didEnterFullscreenForElement(Element* element) { | 517 void Fullscreen::didEnterFullscreenForElement(Element* element) { |
| 506 DCHECK(element); | 518 DCHECK(element); |
| 507 if (!document()->isActive()) | 519 if (!document()->isActive()) |
| 508 return; | 520 return; |
| 509 | 521 |
| 510 if (m_fullScreenLayoutObject) | 522 if (m_fullScreenLayoutObject) |
| 511 m_fullScreenLayoutObject->unwrapLayoutObject(); | 523 m_fullScreenLayoutObject->unwrapLayoutObject(); |
| 512 | 524 |
| 513 m_currentFullScreenElement = element; | 525 m_currentFullScreenElement = element; |
| 514 | 526 |
| 515 // Create a placeholder block for a the full-screen element, to keep the page
from reflowing | 527 // Create a placeholder block for a the full-screen element, to keep the page |
| 516 // when the element is removed from the normal flow. Only do this for a Layout
Box, as only | 528 // from reflowing when the element is removed from the normal flow. Only do |
| 517 // a box will have a frameRect. The placeholder will be created in setFullScre
enLayoutObject() | 529 // this for a LayoutBox, as only a box will have a frameRect. The placeholder |
| 518 // during layout. | 530 // will be created in setFullScreenLayoutObject() during layout. |
| 519 LayoutObject* layoutObject = m_currentFullScreenElement->layoutObject(); | 531 LayoutObject* layoutObject = m_currentFullScreenElement->layoutObject(); |
| 520 bool shouldCreatePlaceholder = layoutObject && layoutObject->isBox(); | 532 bool shouldCreatePlaceholder = layoutObject && layoutObject->isBox(); |
| 521 if (shouldCreatePlaceholder) { | 533 if (shouldCreatePlaceholder) { |
| 522 m_savedPlaceholderFrameRect = toLayoutBox(layoutObject)->frameRect(); | 534 m_savedPlaceholderFrameRect = toLayoutBox(layoutObject)->frameRect(); |
| 523 m_savedPlaceholderComputedStyle = | 535 m_savedPlaceholderComputedStyle = |
| 524 ComputedStyle::clone(layoutObject->styleRef()); | 536 ComputedStyle::clone(layoutObject->styleRef()); |
| 525 } | 537 } |
| 526 | 538 |
| 527 // TODO(alexmos): When |m_forCrossProcessDescendant| is true, some of | 539 // TODO(alexmos): When |m_forCrossProcessDescendant| is true, some of |
| 528 // this layout work has already been done in another process, so it should | 540 // this layout work has already been done in another process, so it should |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 579 if (m_fullScreenLayoutObject) | 591 if (m_fullScreenLayoutObject) |
| 580 LayoutFullScreenItem(m_fullScreenLayoutObject).unwrapLayoutObject(); | 592 LayoutFullScreenItem(m_fullScreenLayoutObject).unwrapLayoutObject(); |
| 581 | 593 |
| 582 document()->styleEngine().ensureFullscreenUAStyle(); | 594 document()->styleEngine().ensureFullscreenUAStyle(); |
| 583 m_currentFullScreenElement->pseudoStateChanged(CSSSelector::PseudoFullScreen); | 595 m_currentFullScreenElement->pseudoStateChanged(CSSSelector::PseudoFullScreen); |
| 584 m_currentFullScreenElement = nullptr; | 596 m_currentFullScreenElement = nullptr; |
| 585 | 597 |
| 586 if (document()->frame()) | 598 if (document()->frame()) |
| 587 document()->frame()->eventHandler().scheduleHoverStateUpdate(); | 599 document()->frame()->eventHandler().scheduleHoverStateUpdate(); |
| 588 | 600 |
| 589 // When fullyExitFullscreen is called, we call exitFullscreen on the topDocume
nt(). That means | 601 // When fullyExitFullscreen is called, we call exitFullscreen on the |
| 590 // that the events will be queued there. So if we have no events here, start t
he timer on the | 602 // topDocument(). That means that the events will be queued there. So if we |
| 591 // exiting document. | 603 // have no events here, start the timer on the exiting document. |
| 592 Document* exitingDocument = document(); | 604 Document* exitingDocument = document(); |
| 593 if (m_eventQueue.isEmpty()) | 605 if (m_eventQueue.isEmpty()) |
| 594 exitingDocument = &topmostLocalAncestor(*document()); | 606 exitingDocument = &topmostLocalAncestor(*document()); |
| 595 DCHECK(exitingDocument); | 607 DCHECK(exitingDocument); |
| 596 from(*exitingDocument).m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); | 608 from(*exitingDocument).m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); |
| 597 | 609 |
| 598 m_forCrossProcessDescendant = false; | 610 m_forCrossProcessDescendant = false; |
| 599 } | 611 } |
| 600 | 612 |
| 601 void Fullscreen::setFullScreenLayoutObject(LayoutFullScreen* layoutObject) { | 613 void Fullscreen::setFullScreenLayoutObject(LayoutFullScreen* layoutObject) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 DCHECK(document.hasFullscreenSupplement()); | 645 DCHECK(document.hasFullscreenSupplement()); |
| 634 Fullscreen& fullscreen = from(document); | 646 Fullscreen& fullscreen = from(document); |
| 635 EventTarget* target = fullscreen.fullscreenElement(); | 647 EventTarget* target = fullscreen.fullscreenElement(); |
| 636 if (!target) | 648 if (!target) |
| 637 target = fullscreen.currentFullScreenElement(); | 649 target = fullscreen.currentFullScreenElement(); |
| 638 if (!target) | 650 if (!target) |
| 639 target = &document; | 651 target = &document; |
| 640 event = createEvent(EventTypeNames::webkitfullscreenchange, *target); | 652 event = createEvent(EventTypeNames::webkitfullscreenchange, *target); |
| 641 } | 653 } |
| 642 m_eventQueue.append(event); | 654 m_eventQueue.append(event); |
| 643 // NOTE: The timer is started in didEnterFullscreenForElement/didExitFullscree
n. | 655 // NOTE: The timer is started in |
| 656 // didEnterFullscreenForElement/didExitFullscreen. |
| 644 } | 657 } |
| 645 | 658 |
| 646 void Fullscreen::enqueueErrorEvent(Element& element, RequestType requestType) { | 659 void Fullscreen::enqueueErrorEvent(Element& element, RequestType requestType) { |
| 647 Event* event; | 660 Event* event; |
| 648 if (requestType == UnprefixedRequest) | 661 if (requestType == UnprefixedRequest) |
| 649 event = createEvent(EventTypeNames::fullscreenerror, element.document()); | 662 event = createEvent(EventTypeNames::fullscreenerror, element.document()); |
| 650 else | 663 else |
| 651 event = createEvent(EventTypeNames::webkitfullscreenerror, element); | 664 event = createEvent(EventTypeNames::webkitfullscreenerror, element); |
| 652 m_eventQueue.append(event); | 665 m_eventQueue.append(event); |
| 653 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); | 666 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); |
| 654 } | 667 } |
| 655 | 668 |
| 656 void Fullscreen::eventQueueTimerFired(TimerBase*) { | 669 void Fullscreen::eventQueueTimerFired(TimerBase*) { |
| 657 HeapDeque<Member<Event>> eventQueue; | 670 HeapDeque<Member<Event>> eventQueue; |
| 658 m_eventQueue.swap(eventQueue); | 671 m_eventQueue.swap(eventQueue); |
| 659 | 672 |
| 660 while (!eventQueue.isEmpty()) { | 673 while (!eventQueue.isEmpty()) { |
| 661 Event* event = eventQueue.takeFirst(); | 674 Event* event = eventQueue.takeFirst(); |
| 662 Node* target = event->target()->toNode(); | 675 Node* target = event->target()->toNode(); |
| 663 | 676 |
| 664 // If the element was removed from our tree, also message the documentElemen
t. | 677 // If the element was removed from our tree, also message the |
| 678 // documentElement. |
| 665 if (!target->isConnected() && document()->documentElement()) { | 679 if (!target->isConnected() && document()->documentElement()) { |
| 666 DCHECK(isPrefixed(event->type())); | 680 DCHECK(isPrefixed(event->type())); |
| 667 eventQueue.append( | 681 eventQueue.append( |
| 668 createEvent(event->type(), *document()->documentElement())); | 682 createEvent(event->type(), *document()->documentElement())); |
| 669 } | 683 } |
| 670 | 684 |
| 671 target->dispatchEvent(event); | 685 target->dispatchEvent(event); |
| 672 } | 686 } |
| 673 } | 687 } |
| 674 | 688 |
| 675 void Fullscreen::elementRemoved(Element& oldNode) { | 689 void Fullscreen::elementRemoved(Element& oldNode) { |
| 676 // Whenever the removing steps run with an |oldNode| and |oldNode| is in its n
ode document's | 690 // Whenever the removing steps run with an |oldNode| and |oldNode| is in its |
| 677 // fullscreen element stack, run these steps: | 691 // node document's fullscreen element stack, run these steps: |
| 678 | 692 |
| 679 // 1. If |oldNode| is at the top of its node document's fullscreen element sta
ck, act as if the | 693 // 1. If |oldNode| is at the top of its node document's fullscreen element |
| 680 // exitFullscreen() method was invoked on that document. | 694 // stack, act as if the exitFullscreen() method was invoked on that document. |
| 681 if (fullscreenElement() == &oldNode) { | 695 if (fullscreenElement() == &oldNode) { |
| 682 exitFullscreen(oldNode.document()); | 696 exitFullscreen(oldNode.document()); |
| 683 return; | 697 return; |
| 684 } | 698 } |
| 685 | 699 |
| 686 // 2. Otherwise, remove |oldNode| from its node document's fullscreen element
stack. | 700 // 2. Otherwise, remove |oldNode| from its node document's fullscreen element |
| 701 // stack. |
| 687 for (size_t i = 0; i < m_fullscreenElementStack.size(); ++i) { | 702 for (size_t i = 0; i < m_fullscreenElementStack.size(); ++i) { |
| 688 if (m_fullscreenElementStack[i].first.get() == &oldNode) { | 703 if (m_fullscreenElementStack[i].first.get() == &oldNode) { |
| 689 m_fullscreenElementStack.remove(i); | 704 m_fullscreenElementStack.remove(i); |
| 690 return; | 705 return; |
| 691 } | 706 } |
| 692 } | 707 } |
| 693 | 708 |
| 694 // NOTE: |oldNode| was not in the fullscreen element stack. | 709 // NOTE: |oldNode| was not in the fullscreen element stack. |
| 695 } | 710 } |
| 696 | 711 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 712 | 727 |
| 713 DEFINE_TRACE(Fullscreen) { | 728 DEFINE_TRACE(Fullscreen) { |
| 714 visitor->trace(m_currentFullScreenElement); | 729 visitor->trace(m_currentFullScreenElement); |
| 715 visitor->trace(m_fullscreenElementStack); | 730 visitor->trace(m_fullscreenElementStack); |
| 716 visitor->trace(m_eventQueue); | 731 visitor->trace(m_eventQueue); |
| 717 Supplement<Document>::trace(visitor); | 732 Supplement<Document>::trace(visitor); |
| 718 ContextLifecycleObserver::trace(visitor); | 733 ContextLifecycleObserver::trace(visitor); |
| 719 } | 734 } |
| 720 | 735 |
| 721 } // namespace blink | 736 } // namespace blink |
| OLD | NEW |