Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(994)

Side by Side Diff: third_party/WebKit/Source/web/FullscreenController.cpp

Issue 2550703002: Move pending state from FullscreenController to Fullscreen (Closed)
Patch Set: tests and documentation Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 19 matching lines...) Expand all
30 30
31 #include "web/FullscreenController.h" 31 #include "web/FullscreenController.h"
32 32
33 #include "core/dom/Document.h" 33 #include "core/dom/Document.h"
34 #include "core/dom/Fullscreen.h" 34 #include "core/dom/Fullscreen.h"
35 #include "core/frame/FrameView.h" 35 #include "core/frame/FrameView.h"
36 #include "core/frame/LocalFrame.h" 36 #include "core/frame/LocalFrame.h"
37 #include "core/frame/PageScaleConstraintsSet.h" 37 #include "core/frame/PageScaleConstraintsSet.h"
38 #include "core/html/HTMLVideoElement.h" 38 #include "core/html/HTMLVideoElement.h"
39 #include "core/layout/LayoutFullScreen.h" 39 #include "core/layout/LayoutFullScreen.h"
40 #include "platform/RuntimeEnabledFeatures.h"
41 #include "public/platform/WebLayerTreeView.h" 40 #include "public/platform/WebLayerTreeView.h"
42 #include "public/web/WebFrameClient.h" 41 #include "public/web/WebFrameClient.h"
43 #include "web/WebLocalFrameImpl.h" 42 #include "web/WebLocalFrameImpl.h"
44 #include "web/WebSettingsImpl.h"
45 #include "web/WebViewImpl.h" 43 #include "web/WebViewImpl.h"
46 44
47 namespace blink { 45 namespace blink {
48 46
49 FullscreenController* FullscreenController::create(WebViewImpl* webViewImpl) { 47 namespace {
50 return new FullscreenController(webViewImpl); 48
49 WebFrameClient& webFrameClient(LocalFrame& frame) {
50 WebLocalFrameImpl* webFrame = WebLocalFrameImpl::fromFrame(frame);
51 DCHECK(webFrame);
52 DCHECK(webFrame->client());
53 return *webFrame->client();
54 }
55
56 } // anonymous namespace
57
58 std::unique_ptr<FullscreenController> FullscreenController::create(
59 WebViewImpl* webViewImpl) {
60 return wrapUnique(new FullscreenController(webViewImpl));
51 } 61 }
52 62
53 FullscreenController::FullscreenController(WebViewImpl* webViewImpl) 63 FullscreenController::FullscreenController(WebViewImpl* webViewImpl)
54 : m_webViewImpl(webViewImpl), 64 : m_webViewImpl(webViewImpl) {}
55 m_haveEnteredFullscreen(false),
56 m_exitFullscreenPageScaleFactor(0),
57 m_needsScrollAndScaleRestore(false),
58 m_isCancelingFullscreen(false) {}
59 65
60 void FullscreenController::didEnterFullscreen() { 66 void FullscreenController::didEnterFullscreen() {
61 if (!m_provisionalFullscreenElement) 67 // |Browser::EnterFullscreenModeForTab()| can enter fullscreen without going
68 // through |Fullscreen::requestFullscreen()|, in which case there will be no
69 // fullscreen element. Do nothing.
70 if (m_state != State::EnteringFullscreen)
62 return; 71 return;
63 72
64 Element* element = m_provisionalFullscreenElement.release(); 73 updatePageScaleConstraints(false);
65 Document& document = element->document(); 74 m_webViewImpl->setPageScaleFactor(1.0f);
66 m_fullscreenFrame = document.frame(); 75 if (m_webViewImpl->mainFrame()->isWebLocalFrame())
76 m_webViewImpl->mainFrame()->setScrollOffset(WebSize());
77 m_webViewImpl->setVisualViewportOffset(FloatPoint());
67 78
68 if (!m_fullscreenFrame) 79 m_state = State::Fullscreen;
69 return;
70 80
71 if (!m_haveEnteredFullscreen) { 81 // Notify all local frames that we have entered fullscreen.
72 updatePageScaleConstraints(false); 82 for (Frame* frame = m_webViewImpl->page()->mainFrame(); frame;
73 m_webViewImpl->setPageScaleFactor(1.0f); 83 frame = frame->tree().traverseNext()) {
74 if (m_webViewImpl->mainFrame()->isWebLocalFrame()) 84 if (!frame->isLocalFrame())
75 m_webViewImpl->mainFrame()->setScrollOffset(WebSize()); 85 continue;
76 m_webViewImpl->setVisualViewportOffset(FloatPoint()); 86 if (Document* document = toLocalFrame(frame)->document()) {
77 m_haveEnteredFullscreen = true; 87 if (Fullscreen* fullscreen = Fullscreen::fromIfExists(*document))
88 fullscreen->didEnterFullscreen();
89 }
78 } 90 }
79
80 Fullscreen::from(document).didEnterFullscreenForElement(element);
81 DCHECK_EQ(Fullscreen::currentFullScreenElementFrom(document), element);
82 } 91 }
83 92
84 void FullscreenController::didExitFullscreen() { 93 void FullscreenController::didExitFullscreen() {
85 if (!m_fullscreenFrame) 94 // The browser process can exit fullscreen at any time, e.g. if the user
95 // presses Esc. After |Browser::EnterFullscreenModeForTab()|,
96 // |Browser::ExitFullscreenModeForTab()| will make it seem like we exit when
97 // not even in fullscreen. Do nothing.
98 if (m_state == State::Initial)
86 return; 99 return;
87 100
88 if (m_haveEnteredFullscreen) 101 updatePageScaleConstraints(true);
89 updatePageScaleConstraints(true);
90 102
91 if (Document* document = m_fullscreenFrame->document()) { 103 // Set |m_state| so that any |exitFullscreen()| calls from within
92 if (Fullscreen* fullscreen = Fullscreen::fromIfExists(*document)) { 104 // |Fullscreen::didExitFullscreen()| do not call
93 Element* element = fullscreen->currentFullScreenElement(); 105 // |WebFrameClient::exitFullscreen()| again.
94 if (element) { 106 // TODO(foolip): Remove this when state changes and events are synchronized
95 // When the client exits from full screen we have to call 107 // with animation frames. https://crbug.com/402376
96 // fullyExitFullscreen to notify the document. While doing that, 108 m_state = State::ExitingFullscreen;
97 // suppress notifications back to the client.
98 m_isCancelingFullscreen = true;
99 Fullscreen::fullyExitFullscreen(*document);
100 m_isCancelingFullscreen = false;
101 109
102 // We need to wait until style and layout are updated in order 110 // Notify all local frames that we have exited fullscreen.
103 // to propertly restore scroll offsets since content may not be 111 // TODO(foolip): This should only need to notify the topmost local roots. That
104 // overflowing in the same way until they do. 112 // doesn't currently work because |Fullscreen::m_currentFullScreenElement|
105 if (m_haveEnteredFullscreen) 113 // isn't set for the topmost document when an iframe goes fullscreen, but can
106 m_needsScrollAndScaleRestore = true; 114 // be done once |m_currentFullScreenElement| is gone and all state is in the
107 115 // fullscreen element stack. https://crbug.com/402421
116 for (Frame* frame = m_webViewImpl->page()->mainFrame(); frame;
117 frame = frame->tree().traverseNext()) {
118 if (!frame->isLocalFrame())
119 continue;
120 if (Document* document = toLocalFrame(frame)->document()) {
121 if (Fullscreen* fullscreen = Fullscreen::fromIfExists(*document))
108 fullscreen->didExitFullscreen(); 122 fullscreen->didExitFullscreen();
109 }
110 } 123 }
111 } 124 }
112 125
113 m_haveEnteredFullscreen = false; 126 // We need to wait until style and layout are updated in order to properly
114 m_fullscreenFrame.clear(); 127 // restore scroll offsets since content may not be overflowing in the same way
128 // until they are.
129 m_state = State::NeedsScrollAndScaleRestore;
115 } 130 }
116 131
117 void FullscreenController::enterFullscreenForElement(Element* element) { 132 void FullscreenController::enterFullscreen(LocalFrame& frame) {
118 // We are already transitioning to fullscreen for a different element. 133 // If already fullscreen or exiting fullscreen, synchronously call
119 if (m_provisionalFullscreenElement) { 134 // |didEnterFullscreen()|. When exiting, the coming |didExitFullscren()| call
120 m_provisionalFullscreenElement = element; 135 // will again notify all frames.
136 if (m_state == State::Fullscreen || m_state == State::ExitingFullscreen) {
137 State oldState = m_state;
138 m_state = State::EnteringFullscreen;
139 didEnterFullscreen();
140 m_state = oldState;
121 return; 141 return;
122 } 142 }
123 143
124 // We are already in fullscreen mode. 144 // We need to store these values here rather than in |didEnterFullscreen()|
125 if (m_fullscreenFrame) { 145 // since by the time the latter is called, a Resize has already occured,
126 m_provisionalFullscreenElement = element; 146 // clamping the scroll offset. Don't save values if we're still waiting to
127 didEnterFullscreen(); 147 // restore a previous set. This can happen if we exit and quickly reenter
128 return; 148 // fullscreen without performing a layout.
149 if (m_state == State::Initial) {
150 m_initialPageScaleFactor = m_webViewImpl->pageScaleFactor();
151 m_initialScrollOffset = m_webViewImpl->mainFrame()->isWebLocalFrame()
152 ? m_webViewImpl->mainFrame()->getScrollOffset()
153 : WebSize();
154 m_initialVisualViewportOffset = m_webViewImpl->visualViewportOffset();
129 } 155 }
130 156
131 // We need to store these values here rather than didEnterFullscreen since 157 // If already entering fullscreen, just wait.
132 // by the time the latter is called, a Resize has already occured, clamping 158 if (m_state == State::EnteringFullscreen)
133 // the scroll offset. Don't save values if we're still waiting to restore 159 return;
134 // a previous set. This can happen if we exit and quickly reenter fullscreen
135 // without performing a layout.
136 if (!m_haveEnteredFullscreen && !m_needsScrollAndScaleRestore) {
137 m_exitFullscreenPageScaleFactor = m_webViewImpl->pageScaleFactor();
138 m_exitFullscreenScrollOffset =
139 m_webViewImpl->mainFrame()->isWebLocalFrame()
140 ? m_webViewImpl->mainFrame()->getScrollOffset()
141 : WebSize();
142 m_exitFullscreenVisualViewportOffset =
143 m_webViewImpl->visualViewportOffset();
144 }
145 160
146 // We need to transition to fullscreen mode. 161 DCHECK(m_state == State::Initial ||
147 WebLocalFrameImpl* frame = 162 m_state == State::NeedsScrollAndScaleRestore);
148 WebLocalFrameImpl::fromFrame(element->document().frame()); 163 webFrameClient(frame).enterFullscreen();
149 if (frame && frame->client()) { 164
150 if (!Fullscreen::from(element->document()).forCrossProcessDescendant()) 165 m_state = State::EnteringFullscreen;
151 frame->client()->enterFullscreen();
152 m_provisionalFullscreenElement = element;
153 }
154 } 166 }
155 167
156 void FullscreenController::exitFullscreen(LocalFrame* frame) { 168 void FullscreenController::exitFullscreen(LocalFrame& frame) {
157 DCHECK(frame); 169 // If not in fullscreen, ignore any attempt to exit. In particular, when
158 170 // entering fullscreen, allow the transition into fullscreen to complete. Note
159 // The client is exiting full screen, so don't send a notification. 171 // that the browser process is ultimately in control and can still exit
160 if (m_isCancelingFullscreen) 172 // fullscreen at any time.
173 if (m_state != State::Fullscreen)
161 return; 174 return;
162 175
163 WebLocalFrameImpl* webFrame = WebLocalFrameImpl::fromFrame(frame); 176 webFrameClient(frame).exitFullscreen();
164 if (webFrame && webFrame->client()) 177
165 webFrame->client()->exitFullscreen(); 178 m_state = State::ExitingFullscreen;
166 } 179 }
167 180
168 void FullscreenController::fullscreenElementChanged(Element* fromElement, 181 void FullscreenController::fullscreenElementChanged(Element* fromElement,
169 Element* toElement) { 182 Element* toElement) {
170 DCHECK_NE(fromElement, toElement); 183 DCHECK_NE(fromElement, toElement);
171 184
172 if (toElement) { 185 if (toElement) {
173 DCHECK(Fullscreen::isCurrentFullScreenElement(*toElement)); 186 DCHECK(Fullscreen::isCurrentFullScreenElement(*toElement));
174 187
175 if (isHTMLVideoElement(*toElement)) { 188 if (isHTMLVideoElement(*toElement)) {
(...skipping 19 matching lines...) Expand all
195 m_webViewImpl->isTransparent()); 208 m_webViewImpl->isTransparent());
196 } 209 }
197 210
198 HTMLVideoElement& videoElement = toHTMLVideoElement(*fromElement); 211 HTMLVideoElement& videoElement = toHTMLVideoElement(*fromElement);
199 videoElement.didExitFullscreen(); 212 videoElement.didExitFullscreen();
200 } 213 }
201 } 214 }
202 } 215 }
203 216
204 void FullscreenController::updateSize() { 217 void FullscreenController::updateSize() {
205 if (!isFullscreen()) 218 DCHECK(m_webViewImpl->page());
219
220 if (m_state != State::Fullscreen)
206 return; 221 return;
207 222
208 updatePageScaleConstraints(false); 223 updatePageScaleConstraints(false);
209 224
210 LayoutFullScreen* layoutObject = 225 // Traverse all local frames and notify the LayoutFullScreen object, if any.
211 Fullscreen::from(*m_fullscreenFrame->document()).fullScreenLayoutObject(); 226 for (Frame* frame = m_webViewImpl->page()->mainFrame(); frame;
212 if (layoutObject) 227 frame = frame->tree().traverseNext()) {
213 layoutObject->updateStyle(); 228 if (!frame->isLocalFrame())
229 continue;
230 if (Document* document = toLocalFrame(frame)->document()) {
231 if (Fullscreen* fullscreen = Fullscreen::fromIfExists(*document)) {
232 if (LayoutFullScreen* layoutObject =
233 fullscreen->fullScreenLayoutObject())
234 layoutObject->updateStyle();
235 }
236 }
237 }
214 } 238 }
215 239
216 void FullscreenController::didUpdateLayout() { 240 void FullscreenController::didUpdateLayout() {
217 if (!m_needsScrollAndScaleRestore) 241 if (m_state != State::NeedsScrollAndScaleRestore)
218 return; 242 return;
219 243
220 // If we re-entered fullscreen before we could restore the scroll and scale 244 m_webViewImpl->setPageScaleFactor(m_initialPageScaleFactor);
221 // don't try restoring them yet. 245 if (m_webViewImpl->mainFrame()->isWebLocalFrame())
222 if (isFullscreen()) 246 m_webViewImpl->mainFrame()->setScrollOffset(WebSize(m_initialScrollOffset));
223 return; 247 m_webViewImpl->setVisualViewportOffset(m_initialVisualViewportOffset);
224 248
225 m_webViewImpl->setPageScaleFactor(m_exitFullscreenPageScaleFactor); 249 m_state = State::Initial;
226 if (m_webViewImpl->mainFrame()->isWebLocalFrame())
227 m_webViewImpl->mainFrame()->setScrollOffset(
228 WebSize(m_exitFullscreenScrollOffset));
229 m_webViewImpl->setVisualViewportOffset(m_exitFullscreenVisualViewportOffset);
230 m_needsScrollAndScaleRestore = false;
231 } 250 }
232 251
233 void FullscreenController::updatePageScaleConstraints(bool removeConstraints) { 252 void FullscreenController::updatePageScaleConstraints(bool removeConstraints) {
234 PageScaleConstraints fullscreenConstraints; 253 PageScaleConstraints fullscreenConstraints;
235 if (!removeConstraints) { 254 if (!removeConstraints) {
236 fullscreenConstraints = PageScaleConstraints(1.0, 1.0, 1.0); 255 fullscreenConstraints = PageScaleConstraints(1.0, 1.0, 1.0);
237 fullscreenConstraints.layoutSize = FloatSize(m_webViewImpl->size()); 256 fullscreenConstraints.layoutSize = FloatSize(m_webViewImpl->size());
238 } 257 }
239 m_webViewImpl->pageScaleConstraintsSet().setFullscreenConstraints( 258 m_webViewImpl->pageScaleConstraintsSet().setFullscreenConstraints(
240 fullscreenConstraints); 259 fullscreenConstraints);
241 m_webViewImpl->pageScaleConstraintsSet().computeFinalConstraints(); 260 m_webViewImpl->pageScaleConstraintsSet().computeFinalConstraints();
242 261
243 // Although we called computedFinalConstraints() above, the "final" 262 // Although we called |computedFinalConstraints()| above, the "final"
244 // constraints are not actually final. They are still subject to scale factor 263 // constraints are not actually final. They are still subject to scale factor
245 // clamping by contents size. Normally they should be dirtied due to 264 // clamping by contents size. Normally they should be dirtied due to contents
246 // contents size mutation after layout, however the contents size is not 265 // size mutation after layout, however the contents size is not guaranteed to
247 // guaranteed to mutate, and the scale factor may remain unclamped. Just 266 // mutate, and the scale factor may remain unclamped. Just fire the event
248 // fire the event again to ensure the final constraints pick up the latest 267 // again to ensure the final constraints pick up the latest contents size.
249 // contents size.
250 m_webViewImpl->didChangeContentsSize(); 268 m_webViewImpl->didChangeContentsSize();
251 if (m_webViewImpl->mainFrameImpl() && 269 if (m_webViewImpl->mainFrameImpl() &&
252 m_webViewImpl->mainFrameImpl()->frameView()) 270 m_webViewImpl->mainFrameImpl()->frameView())
253 m_webViewImpl->mainFrameImpl()->frameView()->setNeedsLayout(); 271 m_webViewImpl->mainFrameImpl()->frameView()->setNeedsLayout();
254 272
255 m_webViewImpl->updateMainFrameLayoutSize(); 273 m_webViewImpl->updateMainFrameLayoutSize();
256 } 274 }
257 275
258 DEFINE_TRACE(FullscreenController) {
259 visitor->trace(m_provisionalFullscreenElement);
260 visitor->trace(m_fullscreenFrame);
261 }
262
263 } // namespace blink 276 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698