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 |