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

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

Issue 2495423004: Convert FullscreenController to use WebCallbacks (Closed)
Patch Set: rebase 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 std::unique_ptr<FullscreenController> FullscreenController::create(
50 return new FullscreenController(webViewImpl); 48 WebViewImpl* webViewImpl) {
49 return wrapUnique(new FullscreenController(webViewImpl));
51 } 50 }
52 51
53 FullscreenController::FullscreenController(WebViewImpl* webViewImpl) 52 FullscreenController::FullscreenController(WebViewImpl* webViewImpl)
54 : m_webViewImpl(webViewImpl), 53 : m_webViewImpl(webViewImpl) {}
55 m_haveEnteredFullscreen(false),
56 m_exitFullscreenPageScaleFactor(0),
57 m_needsScrollAndScaleRestore(false),
58 m_isCancelingFullscreen(false) {}
59 54
60 void FullscreenController::didEnterFullscreen() { 55 void FullscreenController::didEnterFullscreen() {
61 if (!m_provisionalFullscreenElement) 56 // Browser::EnterFullscreenModeForTab can enter fullscreen without going
57 // through Fullscreen::requestFullscreen, in which case there will be no
58 // fullscreen element. Do nothing.
59 if (m_state != State::kEnteringFullscreen)
62 return; 60 return;
63 61
64 Element* element = m_provisionalFullscreenElement.release(); 62 updatePageScaleConstraints(false);
65 Document& document = element->document(); 63 m_webViewImpl->setPageScaleFactor(1.0f);
66 m_fullscreenFrame = document.frame(); 64 if (m_webViewImpl->mainFrame()->isWebLocalFrame())
65 m_webViewImpl->mainFrame()->setScrollOffset(WebSize());
66 m_webViewImpl->setVisualViewportOffset(FloatPoint());
67 67
68 if (!m_fullscreenFrame) 68 DCHECK(!m_callbacksList.isEmpty());
69 return; 69 CallbacksList callbacksList;
70 callbacksList.swap(m_callbacksList);
71 for (auto& callbacks : callbacksList)
72 callbacks->onSuccess();
70 73
71 if (!m_haveEnteredFullscreen) { 74 m_state = State::kFullscreen;
72 updatePageScaleConstraints(false);
73 m_webViewImpl->setPageScaleFactor(1.0f);
74 if (m_webViewImpl->mainFrame()->isWebLocalFrame())
75 m_webViewImpl->mainFrame()->setScrollOffset(WebSize());
76 m_webViewImpl->setVisualViewportOffset(FloatPoint());
77 m_haveEnteredFullscreen = true;
78 }
79
80 Fullscreen::from(document).didEnterFullscreenForElement(element);
81 DCHECK_EQ(Fullscreen::currentFullScreenElementFrom(document), element);
82 } 75 }
83 76
84 void FullscreenController::didExitFullscreen() { 77 void FullscreenController::didExitFullscreen() {
85 if (!m_fullscreenFrame) 78 // The browser process can exit fullscreen at any time, e.g. if the user
79 // presses Esc. After Browser::EnterFullscreenModeForTab,
80 // Browser::ExitFullscreenModeForTab will make it seem like we exit when not
81 // even in fullscreen. Do nothing.
82 if (m_state == State::kInitial)
86 return; 83 return;
87 84
88 if (m_haveEnteredFullscreen) 85 updatePageScaleConstraints(true);
89 updatePageScaleConstraints(true);
90 86
91 if (Document* document = m_fullscreenFrame->document()) { 87 // If we were transitioning into fullscreen, invoke the error callbacks.
92 if (Fullscreen* fullscreen = Fullscreen::fromIfExists(*document)) { 88 if (m_state == State::kEnteringFullscreen) {
93 Element* element = fullscreen->currentFullScreenElement(); 89 DCHECK(!m_callbacksList.isEmpty());
94 if (element) { 90 CallbacksList callbacksList;
95 // When the client exits from full screen we have to call 91 callbacksList.swap(m_callbacksList);
96 // fullyExitFullscreen to notify the document. While doing that, 92 for (auto& callbacks : callbacksList)
97 // suppress notifications back to the client. 93 callbacks->onError();
98 m_isCancelingFullscreen = true; 94 } else {
99 Fullscreen::fullyExitFullscreen(*document); 95 DCHECK(m_callbacksList.isEmpty());
100 m_isCancelingFullscreen = false; 96 }
101 97
102 // We need to wait until style and layout are updated in order 98 // Set m_state so that any calls to enterFullscreen() or exitFullscreen() from
103 // to propertly restore scroll offsets since content may not be 99 // within Fullscreen::didExitFullscreen do nothing.
104 // overflowing in the same way until they do. 100 m_state = State::kExitingFullscreen;
105 if (m_haveEnteredFullscreen)
106 m_needsScrollAndScaleRestore = true;
107 101
102 // Notify all local frames that we have exited fullscreen.
103 // TODO(foolip): This should only need to notify the topmost local roots. That
104 // doesn't currently work because Fullscreen::m_currentFullScreenElement isn't
105 // set for the topmost document when an iframe goes fullscreen, but can be
106 // done once m_currentFullScreenElement is gone and all state is in the
107 // fullscreen element stack. https://crbug.com/402421
108 for (Frame* frame = m_webViewImpl->page()->mainFrame(); frame;
109 frame = frame->tree().traverseNext()) {
110 if (!frame->isLocalFrame())
111 continue;
112 if (Document* document = toLocalFrame(frame)->document()) {
113 if (Fullscreen* fullscreen = Fullscreen::fromIfExists(*document))
108 fullscreen->didExitFullscreen(); 114 fullscreen->didExitFullscreen();
109 }
110 } 115 }
111 } 116 }
112 117
113 m_haveEnteredFullscreen = false; 118 // We need to wait until style and layout are updated in order to properly
114 m_fullscreenFrame.clear(); 119 // restore scroll offsets since content may not be overflowing in the same way
120 // until they are.
121 m_state = State::kNeedsScrollAndScaleRestore;
115 } 122 }
116 123
117 void FullscreenController::enterFullscreenForElement(Element* element) { 124 namespace {
118 // We are already transitioning to fullscreen for a different element. 125
119 if (m_provisionalFullscreenElement) { 126 WebFrameClient& webFrameClient(LocalFrame& frame) {
120 m_provisionalFullscreenElement = element; 127 WebLocalFrameImpl* webFrame = WebLocalFrameImpl::fromFrame(frame);
128 DCHECK(webFrame);
129 DCHECK(webFrame->client());
130 return *webFrame->client();
131 }
132
133 } // anonymous namespace
134
135 void FullscreenController::enterFullscreen(
136 LocalFrame& frame,
137 std::unique_ptr<WebFullscreenCallbacks> callbacks) {
138 // If already in fullscreen, synchronously invoke the success callback.
139 if (m_state == State::kFullscreen) {
140 DCHECK(m_callbacksList.isEmpty());
141 callbacks->onSuccess();
121 return; 142 return;
122 } 143 }
123 144
124 // We are already in fullscreen mode. 145 // While exiting fullscreen, reject any attempt to enter.
125 if (m_fullscreenFrame) { 146 if (m_state == State::kExitingFullscreen) {
126 m_provisionalFullscreenElement = element; 147 callbacks->onError();
127 didEnterFullscreen();
128 return; 148 return;
129 } 149 }
130 150
131 // We need to store these values here rather than didEnterFullscreen since 151 // We need to store these values here rather than didEnterFullscreen since
132 // by the time the latter is called, a Resize has already occured, clamping 152 // by the time the latter is called, a Resize has already occured, clamping
133 // the scroll offset. Don't save values if we're still waiting to restore 153 // the scroll offset. Don't save values if we're still waiting to restore
134 // a previous set. This can happen if we exit and quickly reenter fullscreen 154 // a previous set. This can happen if we exit and quickly reenter fullscreen
135 // without performing a layout. 155 // without performing a layout.
136 if (!m_haveEnteredFullscreen && !m_needsScrollAndScaleRestore) { 156 if (m_state == State::kInitial) {
137 m_exitFullscreenPageScaleFactor = m_webViewImpl->pageScaleFactor(); 157 m_initialPageScaleFactor = m_webViewImpl->pageScaleFactor();
138 m_exitFullscreenScrollOffset = 158 m_initialScrollOffset = m_webViewImpl->mainFrame()->isWebLocalFrame()
139 m_webViewImpl->mainFrame()->isWebLocalFrame() 159 ? m_webViewImpl->mainFrame()->scrollOffset()
140 ? m_webViewImpl->mainFrame()->scrollOffset() 160 : WebSize();
141 : WebSize(); 161 m_initialVisualViewportOffset = m_webViewImpl->visualViewportOffset();
142 m_exitFullscreenVisualViewportOffset =
143 m_webViewImpl->visualViewportOffset();
144 } 162 }
145 163
146 // We need to transition to fullscreen mode. 164 m_callbacksList.append(std::move(callbacks));
147 WebLocalFrameImpl* frame = 165
148 WebLocalFrameImpl::fromFrame(element->document().frame()); 166 // If already entering fullscreen, just wait.
149 if (frame && frame->client()) { 167 if (m_state == State::kEnteringFullscreen)
150 if (!Fullscreen::from(element->document()).forCrossProcessDescendant()) 168 return;
151 frame->client()->enterFullscreen(); 169
152 m_provisionalFullscreenElement = element; 170 DCHECK(m_state == State::kInitial ||
153 } 171 m_state == State::kNeedsScrollAndScaleRestore);
172 webFrameClient(frame).enterFullscreen();
173
174 m_state = State::kEnteringFullscreen;
154 } 175 }
155 176
156 void FullscreenController::exitFullscreen(LocalFrame* frame) { 177 void FullscreenController::exitFullscreen(LocalFrame& frame) {
157 DCHECK(frame); 178 // If not in fullscreen, ignore any attempt to exit. In particular, for
158 179 // State::kEnteringFullscreen, allow the transition into fullscreen to
159 // The client is exiting full screen, so don't send a notification. 180 // complete. Note that the browser process is ultimately in control and can
160 if (m_isCancelingFullscreen) 181 // still (indirecitly) call didExitFullscreen() at any time to exit.
182 if (m_state != State::kFullscreen)
161 return; 183 return;
162 184
163 WebLocalFrameImpl* webFrame = WebLocalFrameImpl::fromFrame(frame); 185 webFrameClient(frame).exitFullscreen();
164 if (webFrame && webFrame->client()) 186
165 webFrame->client()->exitFullscreen(); 187 m_state = State::kExitingFullscreen;
166 } 188 }
167 189
168 void FullscreenController::fullscreenElementChanged(Element* fromElement, 190 void FullscreenController::fullscreenElementChanged(Element* fromElement,
169 Element* toElement) { 191 Element* toElement) {
170 DCHECK_NE(fromElement, toElement); 192 DCHECK_NE(fromElement, toElement);
171 193
172 if (toElement) { 194 if (toElement) {
173 DCHECK(Fullscreen::isCurrentFullScreenElement(*toElement)); 195 DCHECK(Fullscreen::isCurrentFullScreenElement(*toElement));
174 196
175 if (isHTMLVideoElement(*toElement)) { 197 if (isHTMLVideoElement(*toElement)) {
(...skipping 19 matching lines...) Expand all
195 m_webViewImpl->isTransparent()); 217 m_webViewImpl->isTransparent());
196 } 218 }
197 219
198 HTMLVideoElement& videoElement = toHTMLVideoElement(*fromElement); 220 HTMLVideoElement& videoElement = toHTMLVideoElement(*fromElement);
199 videoElement.didExitFullscreen(); 221 videoElement.didExitFullscreen();
200 } 222 }
201 } 223 }
202 } 224 }
203 225
204 void FullscreenController::updateSize() { 226 void FullscreenController::updateSize() {
205 if (!isFullscreen()) 227 DCHECK(m_webViewImpl->page());
228
229 if (m_state != State::kFullscreen)
206 return; 230 return;
207 231
208 updatePageScaleConstraints(false); 232 updatePageScaleConstraints(false);
209 233
210 LayoutFullScreen* layoutObject = 234 // Traverse all local frames and notify the LayoutFullScreen object, if any.
211 Fullscreen::from(*m_fullscreenFrame->document()).fullScreenLayoutObject(); 235 for (Frame* frame = m_webViewImpl->page()->mainFrame(); frame;
212 if (layoutObject) 236 frame = frame->tree().traverseNext()) {
213 layoutObject->updateStyle(); 237 if (!frame->isLocalFrame())
238 continue;
239 if (Document* document = toLocalFrame(frame)->document()) {
240 if (Fullscreen* fullscreen = Fullscreen::fromIfExists(*document)) {
241 if (LayoutFullScreen* layoutObject =
242 fullscreen->fullScreenLayoutObject())
243 layoutObject->updateStyle();
244 }
245 }
246 }
214 } 247 }
215 248
216 void FullscreenController::didUpdateLayout() { 249 void FullscreenController::didUpdateLayout() {
217 if (!m_needsScrollAndScaleRestore) 250 if (m_state != State::kNeedsScrollAndScaleRestore)
218 return; 251 return;
219 252
220 // If we re-entered fullscreen before we could restore the scroll and scale 253 m_webViewImpl->setPageScaleFactor(m_initialPageScaleFactor);
221 // don't try restoring them yet. 254 if (m_webViewImpl->mainFrame()->isWebLocalFrame())
222 if (isFullscreen()) 255 m_webViewImpl->mainFrame()->setScrollOffset(WebSize(m_initialScrollOffset));
223 return; 256 m_webViewImpl->setVisualViewportOffset(m_initialVisualViewportOffset);
224 257
225 m_webViewImpl->setPageScaleFactor(m_exitFullscreenPageScaleFactor); 258 m_state = State::kInitial;
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 } 259 }
232 260
233 void FullscreenController::updatePageScaleConstraints(bool removeConstraints) { 261 void FullscreenController::updatePageScaleConstraints(bool removeConstraints) {
234 PageScaleConstraints fullscreenConstraints; 262 PageScaleConstraints fullscreenConstraints;
235 if (!removeConstraints) { 263 if (!removeConstraints) {
236 fullscreenConstraints = PageScaleConstraints(1.0, 1.0, 1.0); 264 fullscreenConstraints = PageScaleConstraints(1.0, 1.0, 1.0);
237 fullscreenConstraints.layoutSize = FloatSize(m_webViewImpl->size()); 265 fullscreenConstraints.layoutSize = FloatSize(m_webViewImpl->size());
238 } 266 }
239 m_webViewImpl->pageScaleConstraintsSet().setFullscreenConstraints( 267 m_webViewImpl->pageScaleConstraintsSet().setFullscreenConstraints(
240 fullscreenConstraints); 268 fullscreenConstraints);
241 m_webViewImpl->pageScaleConstraintsSet().computeFinalConstraints(); 269 m_webViewImpl->pageScaleConstraintsSet().computeFinalConstraints();
242 270
243 // Although we called computedFinalConstraints() above, the "final" 271 // Although we called computedFinalConstraints() above, the "final"
244 // constraints are not actually final. They are still subject to scale factor 272 // constraints are not actually final. They are still subject to scale factor
245 // clamping by contents size. Normally they should be dirtied due to 273 // clamping by contents size. Normally they should be dirtied due to
246 // contents size mutation after layout, however the contents size is not 274 // contents size mutation after layout, however the contents size is not
247 // guaranteed to mutate, and the scale factor may remain unclamped. Just 275 // guaranteed to mutate, and the scale factor may remain unclamped. Just
248 // fire the event again to ensure the final constraints pick up the latest 276 // fire the event again to ensure the final constraints pick up the latest
249 // contents size. 277 // contents size.
250 m_webViewImpl->didChangeContentsSize(); 278 m_webViewImpl->didChangeContentsSize();
251 if (m_webViewImpl->mainFrameImpl() && 279 if (m_webViewImpl->mainFrameImpl() &&
252 m_webViewImpl->mainFrameImpl()->frameView()) 280 m_webViewImpl->mainFrameImpl()->frameView())
253 m_webViewImpl->mainFrameImpl()->frameView()->setNeedsLayout(); 281 m_webViewImpl->mainFrameImpl()->frameView()->setNeedsLayout();
254 282
255 m_webViewImpl->updateMainFrameLayoutSize(); 283 m_webViewImpl->updateMainFrameLayoutSize();
256 } 284 }
257 285
258 DEFINE_TRACE(FullscreenController) {
259 visitor->trace(m_provisionalFullscreenElement);
260 visitor->trace(m_fullscreenFrame);
261 }
262
263 } // namespace blink 286 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698