OLD | NEW |
| (Empty) |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "components/html_viewer/html_frame.h" | |
6 | |
7 #include <stddef.h> | |
8 #include <algorithm> | |
9 #include <limits> | |
10 #include <utility> | |
11 | |
12 #include "base/bind.h" | |
13 #include "base/single_thread_task_runner.h" | |
14 #include "base/stl_util.h" | |
15 #include "base/strings/string_util.h" | |
16 #include "base/thread_task_runner_handle.h" | |
17 #include "cc/blink/web_layer_impl.h" | |
18 #include "cc/surfaces/surface_id.h" | |
19 #include "components/html_viewer/ax_provider_impl.h" | |
20 #include "components/html_viewer/blink_basic_type_converters.h" | |
21 #include "components/html_viewer/blink_find_type_converters.h" | |
22 #include "components/html_viewer/blink_text_input_type_converters.h" | |
23 #include "components/html_viewer/blink_url_request_type_converters.h" | |
24 #include "components/html_viewer/devtools_agent_impl.h" | |
25 #include "components/html_viewer/geolocation_client_impl.h" | |
26 #include "components/html_viewer/global_state.h" | |
27 #include "components/html_viewer/html_factory.h" | |
28 #include "components/html_viewer/html_frame_delegate.h" | |
29 #include "components/html_viewer/html_frame_properties.h" | |
30 #include "components/html_viewer/html_frame_tree_manager.h" | |
31 #include "components/html_viewer/html_widget.h" | |
32 #include "components/html_viewer/media_factory.h" | |
33 #include "components/html_viewer/stats_collection_controller.h" | |
34 #include "components/html_viewer/touch_handler.h" | |
35 #include "components/html_viewer/web_layer_tree_view_impl.h" | |
36 #include "components/html_viewer/web_storage_namespace_impl.h" | |
37 #include "components/html_viewer/web_url_loader_impl.h" | |
38 #include "components/mus/public/cpp/scoped_window_ptr.h" | |
39 #include "components/mus/public/cpp/window.h" | |
40 #include "components/mus/public/cpp/window_tree_connection.h" | |
41 #include "components/mus/ws/ids.h" | |
42 #include "mojo/common/common_type_converters.h" | |
43 #include "mojo/converters/blink/blink_input_events_type_converters.h" | |
44 #include "mojo/converters/geometry/geometry_type_converters.h" | |
45 #include "mojo/shell/public/cpp/shell.h" | |
46 #include "third_party/WebKit/public/platform/Platform.h" | |
47 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" | |
48 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h" | |
49 #include "third_party/WebKit/public/platform/WebSize.h" | |
50 #include "third_party/WebKit/public/web/WebConsoleMessage.h" | |
51 #include "third_party/WebKit/public/web/WebDocument.h" | |
52 #include "third_party/WebKit/public/web/WebElement.h" | |
53 #include "third_party/WebKit/public/web/WebFindOptions.h" | |
54 #include "third_party/WebKit/public/web/WebFrameOwnerProperties.h" | |
55 #include "third_party/WebKit/public/web/WebInputEvent.h" | |
56 #include "third_party/WebKit/public/web/WebKit.h" | |
57 #include "third_party/WebKit/public/web/WebLocalFrame.h" | |
58 #include "third_party/WebKit/public/web/WebNavigationPolicy.h" | |
59 #include "third_party/WebKit/public/web/WebRemoteFrame.h" | |
60 #include "third_party/WebKit/public/web/WebRemoteFrameClient.h" | |
61 #include "third_party/WebKit/public/web/WebScriptSource.h" | |
62 #include "third_party/WebKit/public/web/WebView.h" | |
63 #include "ui/gfx/geometry/dip_util.h" | |
64 #include "ui/gfx/geometry/size.h" | |
65 #include "url/gurl.h" | |
66 #include "url/origin.h" | |
67 #include "url/url_constants.h" | |
68 | |
69 using mojo::AxProvider; | |
70 using mojo::Rect; | |
71 using mojo::ServiceProviderPtr; | |
72 using mojo::URLResponsePtr; | |
73 using web_view::mojom::HTMLMessageEvent; | |
74 using web_view::mojom::HTMLMessageEventPtr; | |
75 | |
76 namespace html_viewer { | |
77 namespace { | |
78 | |
79 const size_t kMaxTitleChars = 4 * 1024; | |
80 | |
81 web_view::mojom::NavigationTargetType WebNavigationPolicyToNavigationTarget( | |
82 blink::WebNavigationPolicy policy) { | |
83 switch (policy) { | |
84 case blink::WebNavigationPolicyCurrentTab: | |
85 return web_view::mojom::NavigationTargetType::EXISTING_FRAME; | |
86 case blink::WebNavigationPolicyNewBackgroundTab: | |
87 case blink::WebNavigationPolicyNewForegroundTab: | |
88 case blink::WebNavigationPolicyNewWindow: | |
89 case blink::WebNavigationPolicyNewPopup: | |
90 return web_view::mojom::NavigationTargetType::NEW_FRAME; | |
91 default: | |
92 return web_view::mojom::NavigationTargetType::NO_PREFERENCE; | |
93 } | |
94 } | |
95 | |
96 HTMLFrame* GetPreviousSibling(HTMLFrame* frame) { | |
97 DCHECK(frame->parent()); | |
98 auto iter = std::find(frame->parent()->children().begin(), | |
99 frame->parent()->children().end(), frame); | |
100 return (iter == frame->parent()->children().begin()) ? nullptr : *(--iter); | |
101 } | |
102 | |
103 // See surface_layer.h for a description of this callback. | |
104 void SatisfyCallback(cc::SurfaceSequence sequence) { | |
105 // TODO(fsamuel): Implement this. | |
106 } | |
107 | |
108 // See surface_layer.h for a description of this callback. | |
109 void RequireCallback(cc::SurfaceId surface_id, | |
110 cc::SurfaceSequence sequence) { | |
111 // TODO(fsamuel): Implement this. | |
112 } | |
113 | |
114 } // namespace | |
115 | |
116 HTMLFrame::HTMLFrame(CreateParams* params) | |
117 : frame_tree_manager_(params->manager), | |
118 parent_(params->parent), | |
119 window_(nullptr), | |
120 id_(params->id), | |
121 web_frame_(nullptr), | |
122 delegate_(params->delegate), | |
123 pending_navigation_(false), | |
124 weak_factory_(this) { | |
125 TRACE_EVENT0("html_viewer", "HTMLFrame::HTMLFrame"); | |
126 if (parent_) | |
127 parent_->children_.push_back(this); | |
128 | |
129 if (params->window && params->window->id() == id_) | |
130 SetWindow(params->window); | |
131 | |
132 SetReplicatedFrameStateFromClientProperties(params->properties, &state_); | |
133 | |
134 if (!parent_) { | |
135 CreateRootWebWidget(); | |
136 | |
137 // This is the root of the tree (aka the main frame). | |
138 // Expected order for creating webframes is: | |
139 // . Create local webframe (first webframe must always be local). | |
140 // . Set as main frame on WebView. | |
141 // . Swap to remote (if not local). | |
142 blink::WebLocalFrame* local_web_frame = | |
143 blink::WebLocalFrame::create(state_.tree_scope, this); | |
144 // We need to set the main frame before creating children so that state is | |
145 // properly set up in blink. | |
146 web_view()->setMainFrame(local_web_frame); | |
147 | |
148 // The resize and setDeviceScaleFactor() needs to be after setting the main | |
149 // frame. | |
150 const gfx::Size size_in_pixels(params->window->bounds().size()); | |
151 const gfx::Size size_in_dips = gfx::ConvertSizeToDIP( | |
152 params->window->viewport_metrics().device_pixel_ratio, size_in_pixels); | |
153 web_view()->resize(size_in_dips); | |
154 web_frame_ = local_web_frame; | |
155 web_view()->setDeviceScaleFactor(global_state()->device_pixel_ratio()); | |
156 if (id_ != params->window->id()) { | |
157 blink::WebRemoteFrame* remote_web_frame = | |
158 blink::WebRemoteFrame::create(state_.tree_scope, this); | |
159 local_web_frame->swap(remote_web_frame); | |
160 web_frame_ = remote_web_frame; | |
161 } else { | |
162 // Setup a DevTools agent if this is the local main frame and the browser | |
163 // side has set relevant client properties. | |
164 mojo::Array<uint8_t> devtools_id = | |
165 GetValueFromClientProperties("devtools-id", params->properties); | |
166 if (!devtools_id.is_null()) { | |
167 mojo::Array<uint8_t> devtools_state = | |
168 GetValueFromClientProperties("devtools-state", params->properties); | |
169 std::string devtools_state_str = devtools_state.To<std::string>(); | |
170 devtools_agent_.reset(new DevToolsAgentImpl( | |
171 web_frame_->toWebLocalFrame(), devtools_id.To<std::string>(), | |
172 devtools_state.is_null() ? nullptr : &devtools_state_str)); | |
173 } | |
174 | |
175 // Collect startup perf data for local main frames in test environments. | |
176 // Child frames aren't tracked, and tracking remote frames is redundant. | |
177 startup_performance_data_collector_ = | |
178 StatsCollectionController::Install(web_frame_, GetShell()); | |
179 } | |
180 } else if (!params->is_local_create_child && params->window && | |
181 id_ == params->window->id()) { | |
182 // Frame represents the local frame, and it isn't the root of the tree. | |
183 HTMLFrame* previous_sibling = GetPreviousSibling(this); | |
184 blink::WebFrame* previous_web_frame = | |
185 previous_sibling ? previous_sibling->web_frame() : nullptr; | |
186 CHECK(!parent_->IsLocal()); | |
187 web_frame_ = parent_->web_frame()->toWebRemoteFrame()->createLocalChild( | |
188 state_.tree_scope, state_.name, state_.sandbox_flags, this, | |
189 previous_web_frame, | |
190 // TODO(lazyboy): Replicate WebFrameOwnerProperties where needed. | |
191 blink::WebFrameOwnerProperties()); | |
192 CreateLocalRootWebWidget(web_frame_->toWebLocalFrame()); | |
193 } else if (!parent_->IsLocal()) { | |
194 web_frame_ = parent_->web_frame()->toWebRemoteFrame()->createRemoteChild( | |
195 state_.tree_scope, state_.name, state_.sandbox_flags, this); | |
196 } else { | |
197 CHECK(params->is_local_create_child); | |
198 | |
199 blink::WebLocalFrame* child_web_frame = | |
200 blink::WebLocalFrame::create(state_.tree_scope, this); | |
201 web_frame_ = child_web_frame; | |
202 parent_->web_frame_->appendChild(child_web_frame); | |
203 } | |
204 | |
205 DVLOG(2) << "HTMLFrame init this=" << this << " id=" << id_ | |
206 << " local=" << IsLocal() | |
207 << " parent=" << (parent_ ? parent_->id_ : 0u); | |
208 | |
209 if (!IsLocal()) { | |
210 blink::WebRemoteFrame* remote_web_frame = web_frame_->toWebRemoteFrame(); | |
211 if (remote_web_frame) { | |
212 remote_web_frame->setReplicatedOrigin(state_.origin); | |
213 remote_web_frame->setReplicatedName(state_.name); | |
214 } | |
215 } | |
216 } | |
217 | |
218 void HTMLFrame::Close() { | |
219 if (GetWebWidget()) { | |
220 // Closing the root widget (WebView) implicitly detaches. For children | |
221 // (which have a WebFrameWidget) a detach() is required. Use a temporary | |
222 // as if 'this' is the root the call to GetWebWidget()->close() deletes | |
223 // 'this'. | |
224 const bool is_child = parent_ != nullptr; | |
225 GetWebWidget()->close(); | |
226 if (is_child) | |
227 web_frame_->detach(); | |
228 } else { | |
229 web_frame_->detach(); | |
230 } | |
231 } | |
232 | |
233 const HTMLFrame* HTMLFrame::FindFrame(uint32_t id) const { | |
234 if (id == id_) | |
235 return this; | |
236 | |
237 for (const HTMLFrame* child : children_) { | |
238 const HTMLFrame* match = child->FindFrame(id); | |
239 if (match) | |
240 return match; | |
241 } | |
242 return nullptr; | |
243 } | |
244 | |
245 blink::WebView* HTMLFrame::web_view() { | |
246 blink::WebWidget* web_widget = | |
247 html_widget_ ? html_widget_->GetWidget() : nullptr; | |
248 return web_widget && web_widget->isWebView() | |
249 ? static_cast<blink::WebView*>(web_widget) | |
250 : nullptr; | |
251 } | |
252 | |
253 blink::WebWidget* HTMLFrame::GetWebWidget() { | |
254 return html_widget_ ? html_widget_->GetWidget() : nullptr; | |
255 } | |
256 | |
257 bool HTMLFrame::IsLocal() const { | |
258 return web_frame_->isWebLocalFrame(); | |
259 } | |
260 | |
261 bool HTMLFrame::HasLocalDescendant() const { | |
262 if (IsLocal()) | |
263 return true; | |
264 | |
265 for (HTMLFrame* child : children_) { | |
266 if (child->HasLocalDescendant()) | |
267 return true; | |
268 } | |
269 return false; | |
270 } | |
271 | |
272 void HTMLFrame::LoadRequest(const blink::WebURLRequest& request, | |
273 base::TimeTicks navigation_start_time) { | |
274 TRACE_EVENT1("html_viewer", "HTMLFrame::LoadRequest", | |
275 "url", request.url().string().utf8()); | |
276 | |
277 DCHECK(IsLocal()); | |
278 | |
279 DVLOG(2) << "HTMLFrame::LoadRequest this=" << this << " id=" << id_ | |
280 << " URL=" << GURL(request.url()); | |
281 | |
282 pending_navigation_ = false; | |
283 navigation_start_time_ = navigation_start_time; | |
284 web_frame_->toWebLocalFrame()->loadRequest(request); | |
285 } | |
286 | |
287 HTMLFrame::~HTMLFrame() { | |
288 DVLOG(2) << "~HTMLFrame this=" << this << " id=" << id_; | |
289 | |
290 DCHECK(children_.empty()); | |
291 | |
292 if (parent_) { | |
293 auto iter = | |
294 std::find(parent_->children_.begin(), parent_->children_.end(), this); | |
295 parent_->children_.erase(iter); | |
296 } | |
297 parent_ = nullptr; | |
298 | |
299 frame_tree_manager_->OnFrameDestroyed(this); | |
300 | |
301 if (delegate_) | |
302 delegate_->OnFrameDestroyed(); | |
303 | |
304 if (window_) { | |
305 window_->RemoveObserver(this); | |
306 mus::ScopedWindowPtr::DeleteWindowOrWindowManager(window_); | |
307 } | |
308 } | |
309 | |
310 blink::WebMediaPlayer* HTMLFrame::createMediaPlayer( | |
311 blink::WebLocalFrame* frame, | |
312 blink::WebMediaPlayer::LoadType load_type, | |
313 const blink::WebURL& url, | |
314 blink::WebMediaPlayerClient* client, | |
315 blink::WebMediaPlayerEncryptedMediaClient* encrypted_client, | |
316 blink::WebContentDecryptionModule* initial_cdm, | |
317 const blink::WebString& sink_id, | |
318 blink::WebMediaSession* media_session) { | |
319 return global_state()->media_factory()->CreateMediaPlayer( | |
320 frame, url, client, encrypted_client, initial_cdm, GetShell()); | |
321 } | |
322 | |
323 blink::WebFrame* HTMLFrame::createChildFrame( | |
324 blink::WebLocalFrame* parent, | |
325 blink::WebTreeScopeType scope, | |
326 const blink::WebString& frame_name, | |
327 blink::WebSandboxFlags sandbox_flags, | |
328 const blink::WebFrameOwnerProperties& frame_owner_properties) { | |
329 DCHECK(IsLocal()); // Can't create children of remote frames. | |
330 DCHECK_EQ(parent, web_frame_); | |
331 DCHECK(window_); // If we're local we have to have a window. | |
332 // Create the window that will house the frame now. We embed once we know the | |
333 // url (see decidePolicyForNavigation()). | |
334 mus::Window* child_window = window_->connection()->NewWindow(); | |
335 ReplicatedFrameState child_state; | |
336 child_state.name = frame_name; | |
337 child_state.tree_scope = scope; | |
338 child_state.sandbox_flags = sandbox_flags; | |
339 mojo::Map<mojo::String, mojo::Array<uint8_t>> client_properties; | |
340 client_properties.mark_non_null(); | |
341 ClientPropertiesFromReplicatedFrameState(child_state, &client_properties); | |
342 | |
343 child_window->SetVisible(true); | |
344 window_->AddChild(child_window); | |
345 | |
346 HTMLFrame::CreateParams params(frame_tree_manager_, this, child_window->id(), | |
347 child_window, client_properties, nullptr); | |
348 params.is_local_create_child = true; | |
349 HTMLFrame* child_frame = GetFirstAncestorWithDelegate() | |
350 ->delegate_->GetHTMLFactory() | |
351 ->CreateHTMLFrame(¶ms); | |
352 child_frame->owned_window_.reset(new mus::ScopedWindowPtr(child_window)); | |
353 | |
354 web_view::mojom::FrameClientPtr client_ptr; | |
355 child_frame->frame_client_binding_.reset( | |
356 new mojo::Binding<web_view::mojom::FrameClient>( | |
357 child_frame, mojo::GetProxy(&client_ptr))); | |
358 server_->OnCreatedFrame(GetProxy(&(child_frame->server_)), | |
359 std::move(client_ptr), child_window->id(), | |
360 std::move(client_properties)); | |
361 return child_frame->web_frame_; | |
362 } | |
363 | |
364 void HTMLFrame::frameDetached(blink::WebFrame* web_frame, | |
365 blink::WebFrameClient::DetachType type) { | |
366 if (type == blink::WebFrameClient::DetachType::Swap) { | |
367 web_frame->close(); | |
368 return; | |
369 } | |
370 | |
371 DCHECK(type == blink::WebFrameClient::DetachType::Remove); | |
372 FrameDetachedImpl(web_frame); | |
373 } | |
374 | |
375 blink::WebCookieJar* HTMLFrame::cookieJar(blink::WebLocalFrame* frame) { | |
376 // TODO(darin): Blink does not fallback to the Platform provided WebCookieJar. | |
377 // Either it should, as it once did, or we should find another solution here. | |
378 return blink::Platform::current()->cookieJar(); | |
379 } | |
380 | |
381 blink::WebNavigationPolicy HTMLFrame::decidePolicyForNavigation( | |
382 const NavigationPolicyInfo& info) { | |
383 // If we have extraData() it means we already have the url response | |
384 // (presumably because we are being called via Navigate()). In that case we | |
385 // can go ahead and navigate locally. | |
386 if (info.urlRequest.extraData()) { | |
387 DCHECK_EQ(blink::WebNavigationPolicyCurrentTab, info.defaultPolicy); | |
388 return blink::WebNavigationPolicyCurrentTab; | |
389 } | |
390 | |
391 // about:blank is treated as the same origin and is always allowed for frames. | |
392 if (parent_ && info.urlRequest.url() == GURL(url::kAboutBlankURL) && | |
393 info.defaultPolicy == blink::WebNavigationPolicyCurrentTab) { | |
394 return blink::WebNavigationPolicyCurrentTab; | |
395 } | |
396 | |
397 // Ask the Frame to handle the navigation. Returning | |
398 // WebNavigationPolicyHandledByClient to inform blink that the navigation is | |
399 // being handled. | |
400 DVLOG(2) << "HTMLFrame::decidePolicyForNavigation calls " | |
401 << "Frame::RequestNavigate this=" << this << " id=" << id_ | |
402 << " URL=" << GURL(info.urlRequest.url()); | |
403 | |
404 mojo::URLRequestPtr url_request = mojo::URLRequest::From(info.urlRequest); | |
405 url_request->originating_time_ticks = | |
406 base::TimeTicks::Now().ToInternalValue(); | |
407 server_->RequestNavigate( | |
408 WebNavigationPolicyToNavigationTarget(info.defaultPolicy), id_, | |
409 std::move(url_request)); | |
410 | |
411 // TODO(yzshen): crbug.com/532556 If the server side drops the request, | |
412 // this frame will be in permenant-loading state. We should send a | |
413 // notification to mark this frame as not loading in that case. We also need | |
414 // to better keep track of multiple pending navigations. | |
415 pending_navigation_ = true; | |
416 return blink::WebNavigationPolicyHandledByClient; | |
417 } | |
418 | |
419 bool HTMLFrame::hasPendingNavigation(blink::WebLocalFrame* frame) { | |
420 return pending_navigation_; | |
421 } | |
422 | |
423 void HTMLFrame::didHandleOnloadEvents(blink::WebLocalFrame* frame) { | |
424 DVLOG(2) << "XXX HTMLFrame::didHandleOnloadEvents id=" << id_; | |
425 static bool recorded = false; | |
426 if (!recorded && startup_performance_data_collector_) { | |
427 startup_performance_data_collector_->SetFirstWebContentsMainFrameLoadTicks( | |
428 base::TimeTicks::Now().ToInternalValue()); | |
429 recorded = true; | |
430 } | |
431 } | |
432 | |
433 void HTMLFrame::didAddMessageToConsole(const blink::WebConsoleMessage& message, | |
434 const blink::WebString& source_name, | |
435 unsigned source_line, | |
436 const blink::WebString& stack_trace) { | |
437 VLOG(1) << "[" << source_name.utf8() << "(" << source_line << ")] " | |
438 << message.text.utf8(); | |
439 } | |
440 | |
441 void HTMLFrame::didFinishLoad(blink::WebLocalFrame* frame) { | |
442 if (GetFirstAncestorWithDelegate() == this) | |
443 delegate_->OnFrameDidFinishLoad(); | |
444 } | |
445 | |
446 void HTMLFrame::didNavigateWithinPage(blink::WebLocalFrame* frame, | |
447 const blink::WebHistoryItem& history_item, | |
448 blink::WebHistoryCommitType commit_type) { | |
449 server_->DidNavigateLocally(history_item.urlString().utf8()); | |
450 } | |
451 | |
452 blink::WebGeolocationClient* HTMLFrame::geolocationClient() { | |
453 if (!geolocation_client_impl_) | |
454 geolocation_client_impl_.reset(new GeolocationClientImpl); | |
455 return geolocation_client_impl_.get(); | |
456 } | |
457 | |
458 blink::WebEncryptedMediaClient* HTMLFrame::encryptedMediaClient() { | |
459 return global_state()->media_factory()->GetEncryptedMediaClient(); | |
460 } | |
461 | |
462 void HTMLFrame::didStartLoading(bool to_different_document) { | |
463 server_->LoadingStateChanged(true, 0.0); | |
464 } | |
465 | |
466 void HTMLFrame::didStopLoading() { | |
467 server_->LoadingStateChanged(false, 1.0); | |
468 } | |
469 | |
470 void HTMLFrame::didChangeLoadProgress(double load_progress) { | |
471 server_->LoadingStateChanged(true, load_progress); | |
472 } | |
473 | |
474 void HTMLFrame::dispatchLoad() { | |
475 // According to comments of WebFrameClient::dispatchLoad(), this should only | |
476 // be called when the parent frame is remote. | |
477 DCHECK(parent_ && !parent_->IsLocal()); | |
478 server_->DispatchLoadEventToParent(); | |
479 } | |
480 | |
481 void HTMLFrame::didChangeName(blink::WebLocalFrame* frame, | |
482 const blink::WebString& name) { | |
483 state_.name = name; | |
484 server_->SetClientProperty(kPropertyFrameName, | |
485 FrameNameToClientProperty(name)); | |
486 } | |
487 | |
488 void HTMLFrame::didCommitProvisionalLoad( | |
489 blink::WebLocalFrame* frame, | |
490 const blink::WebHistoryItem& item, | |
491 blink::WebHistoryCommitType commit_type) { | |
492 state_.origin = FrameOrigin(frame); | |
493 server_->SetClientProperty(kPropertyFrameOrigin, | |
494 FrameOriginToClientProperty(frame)); | |
495 | |
496 // TODO(erg): We need to pass way more information from here through to the | |
497 // other side. See FrameHostMsg_DidCommitProvisionalLoad_Params. It is a grab | |
498 // bag of everything and it looks like a combination of | |
499 // NavigatorImpl::DidNavigate and | |
500 // NavigationControllerImpl::RendererDidNavigate use everything passed | |
501 // through. | |
502 server_->DidCommitProvisionalLoad(); | |
503 | |
504 if (!navigation_start_time_.is_null()) { | |
505 frame->dataSource()->setNavigationStartTime( | |
506 navigation_start_time_.ToInternalValue() / | |
507 static_cast<double>(base::Time::kMicrosecondsPerSecond)); | |
508 navigation_start_time_ = base::TimeTicks(); | |
509 } | |
510 } | |
511 | |
512 void HTMLFrame::didReceiveTitle(blink::WebLocalFrame* frame, | |
513 const blink::WebString& title, | |
514 blink::WebTextDirection direction) { | |
515 // TODO(beng): handle |direction|. | |
516 mojo::String formatted; | |
517 if (!title.isNull()) { | |
518 formatted = | |
519 mojo::String::From(base::string16(title).substr(0, kMaxTitleChars)); | |
520 } | |
521 server_->TitleChanged(formatted); | |
522 } | |
523 | |
524 void HTMLFrame::reportFindInFrameMatchCount(int identifier, | |
525 int count, | |
526 bool finalUpdate) { | |
527 server_->OnFindInFrameCountUpdated(identifier, count, finalUpdate); | |
528 } | |
529 | |
530 void HTMLFrame::reportFindInPageSelection(int identifier, | |
531 int activeMatchOrdinal, | |
532 const blink::WebRect& selection) { | |
533 server_->OnFindInPageSelectionUpdated(identifier, activeMatchOrdinal); | |
534 } | |
535 | |
536 bool HTMLFrame::shouldSearchSingleFrame() { | |
537 return true; | |
538 } | |
539 | |
540 void HTMLFrame::Bind( | |
541 web_view::mojom::FramePtr frame, | |
542 mojo::InterfaceRequest<web_view::mojom::FrameClient> frame_client_request) { | |
543 DCHECK(IsLocal()); | |
544 server_ = std::move(frame); | |
545 server_.set_connection_error_handler( | |
546 base::Bind(&HTMLFrame::Close, base::Unretained(this))); | |
547 frame_client_binding_.reset(new mojo::Binding<web_view::mojom::FrameClient>( | |
548 this, std::move(frame_client_request))); | |
549 } | |
550 | |
551 void HTMLFrame::SetValueFromClientProperty(const std::string& name, | |
552 mojo::Array<uint8_t> new_data) { | |
553 if (IsLocal()) | |
554 return; | |
555 | |
556 // Only the name and origin dynamically change. | |
557 if (name == kPropertyFrameOrigin) { | |
558 state_.origin = FrameOriginFromClientProperty(new_data); | |
559 web_frame_->toWebRemoteFrame()->setReplicatedOrigin(state_.origin); | |
560 } else if (name == kPropertyFrameName) { | |
561 state_.name = FrameNameFromClientProperty(new_data); | |
562 web_frame_->toWebRemoteFrame()->setReplicatedName(state_.name); | |
563 } | |
564 } | |
565 | |
566 HTMLFrame* HTMLFrame::GetFirstAncestorWithDelegate() { | |
567 HTMLFrame* frame = this; | |
568 while (frame && !frame->delegate_) | |
569 frame = frame->parent_; | |
570 return frame; | |
571 } | |
572 | |
573 mojo::Shell* HTMLFrame::GetShell() { | |
574 return GetFirstAncestorWithDelegate()->delegate_->GetShell(); | |
575 } | |
576 | |
577 web_view::mojom::Frame* HTMLFrame::GetServerFrame() { | |
578 // Prefer an ancestor with a server Frame. | |
579 for (HTMLFrame* frame = this; frame; frame = frame->parent_) { | |
580 if (frame->server_.get()) | |
581 return frame->server_.get(); | |
582 } | |
583 | |
584 // We're a remote frame with no local frame ancestors. Use the server Frame | |
585 // from the local frame of the HTMLFrameTreeManager. | |
586 return frame_tree_manager_->local_frame_->server_.get(); | |
587 } | |
588 | |
589 void HTMLFrame::SetWindow(mus::Window* window) { | |
590 if (window_) { | |
591 window_->set_input_event_handler(nullptr); | |
592 window_->RemoveObserver(this); | |
593 } | |
594 window_ = window; | |
595 if (window_) { | |
596 window_->AddObserver(this); | |
597 window_->set_input_event_handler(this); | |
598 } | |
599 } | |
600 | |
601 void HTMLFrame::CreateRootWebWidget() { | |
602 DCHECK(!html_widget_); | |
603 if (window_) { | |
604 HTMLWidgetRootLocal::CreateParams create_params(GetShell(), global_state(), | |
605 window_); | |
606 html_widget_.reset( | |
607 delegate_->GetHTMLFactory()->CreateHTMLWidgetRootLocal(&create_params)); | |
608 } else { | |
609 html_widget_.reset(new HTMLWidgetRootRemote(global_state())); | |
610 } | |
611 } | |
612 | |
613 void HTMLFrame::CreateLocalRootWebWidget(blink::WebLocalFrame* local_frame) { | |
614 DCHECK(!html_widget_); | |
615 DCHECK(IsLocal()); | |
616 html_widget_.reset(new HTMLWidgetLocalRoot(GetShell(), global_state(), | |
617 window_, local_frame)); | |
618 } | |
619 | |
620 void HTMLFrame::UpdateFocus() { | |
621 blink::WebWidget* web_widget = GetWebWidget(); | |
622 if (!web_widget || !window_) | |
623 return; | |
624 const bool is_focused = window_ && window_->HasFocus(); | |
625 web_widget->setFocus(is_focused); | |
626 if (web_widget->isWebView()) | |
627 static_cast<blink::WebView*>(web_widget)->setIsActive(is_focused); | |
628 } | |
629 | |
630 void HTMLFrame::SwapToRemote() { | |
631 TRACE_EVENT0("html_viewer", "HTMLFrame::SwapToRemote"); | |
632 | |
633 DVLOG(2) << "HTMLFrame::SwapToRemote this=" << this << " id=" << id_; | |
634 | |
635 DCHECK(IsLocal()); | |
636 | |
637 HTMLFrameDelegate* delegate = delegate_; | |
638 delegate_ = nullptr; | |
639 | |
640 blink::WebRemoteFrame* remote_frame = | |
641 blink::WebRemoteFrame::create(state_.tree_scope, this); | |
642 remote_frame->initializeFromFrame(web_frame_->toWebLocalFrame()); | |
643 // swap() ends up calling us back and we then close the frame, which deletes | |
644 // it. | |
645 web_frame_->swap(remote_frame); | |
646 if (owned_window_) { | |
647 surface_layer_ = | |
648 cc::SurfaceLayer::Create(cc_blink::WebLayerImpl::LayerSettings(), | |
649 base::Bind(&SatisfyCallback), | |
650 base::Bind(&RequireCallback)); | |
651 surface_layer_->SetSurfaceId(cc::SurfaceId(owned_window_->window()->id()), | |
652 global_state()->device_pixel_ratio(), | |
653 owned_window_->window()->bounds().size()); | |
654 | |
655 web_layer_.reset(new cc_blink::WebLayerImpl(surface_layer_)); | |
656 } | |
657 remote_frame->setRemoteWebLayer(web_layer_.get()); | |
658 remote_frame->setReplicatedName(state_.name); | |
659 remote_frame->setReplicatedOrigin(state_.origin); | |
660 remote_frame->setReplicatedSandboxFlags(state_.sandbox_flags); | |
661 | |
662 // Tell the frame that it is actually loading. This prevents its parent | |
663 // from prematurely dispatching load event. | |
664 remote_frame->didStartLoading(); | |
665 pending_navigation_ = false; | |
666 | |
667 web_frame_ = remote_frame; | |
668 SetWindow(nullptr); | |
669 server_.reset(); | |
670 frame_client_binding_.reset(); | |
671 if (delegate) | |
672 delegate->OnFrameSwappedToRemote(); | |
673 } | |
674 | |
675 void HTMLFrame::SwapToLocal( | |
676 HTMLFrameDelegate* delegate, | |
677 mus::Window* window, | |
678 const mojo::Map<mojo::String, mojo::Array<uint8_t>>& properties) { | |
679 TRACE_EVENT0("html_viewer", "HTMLFrame::SwapToLocal"); | |
680 DVLOG(2) << "HTMLFrame::SwapToLocal this=" << this << " id=" << id_; | |
681 CHECK(!IsLocal()); | |
682 // It doesn't make sense for the root to swap to local. | |
683 CHECK(parent_); | |
684 delegate_ = delegate; | |
685 SetWindow(window); | |
686 SetReplicatedFrameStateFromClientProperties(properties, &state_); | |
687 blink::WebLocalFrame* local_web_frame = | |
688 blink::WebLocalFrame::createProvisional( | |
689 this, web_frame_->toWebRemoteFrame(), state_.sandbox_flags, | |
690 // TODO(lazyboy): Figure out replicating WebFrameOwnerProperties. | |
691 blink::WebFrameOwnerProperties()); | |
692 // The swap() ends up calling to frameDetached() and deleting the old. | |
693 web_frame_->swap(local_web_frame); | |
694 web_frame_ = local_web_frame; | |
695 | |
696 web_layer_.reset(); | |
697 } | |
698 | |
699 void HTMLFrame::SwapDelegate(HTMLFrameDelegate* delegate) { | |
700 DCHECK(IsLocal()); | |
701 HTMLFrameDelegate* old_delegate = delegate_; | |
702 delegate_ = delegate; | |
703 delegate->OnSwap(this, old_delegate); | |
704 } | |
705 | |
706 blink::WebElement HTMLFrame::GetFocusedElement() { | |
707 if (!web_view()) | |
708 return blink::WebElement(); | |
709 | |
710 HTMLFrame* frame = this; | |
711 while (frame) { | |
712 if (frame->web_view()) { | |
713 if (frame->web_view()->focusedFrame() == web_frame_) { | |
714 blink::WebDocument doc = web_frame_->document(); | |
715 if (!doc.isNull()) | |
716 return doc.focusedElement(); | |
717 } | |
718 return blink::WebElement(); | |
719 } | |
720 frame = frame->parent(); | |
721 } | |
722 | |
723 return blink::WebElement(); | |
724 } | |
725 | |
726 HTMLFrame* HTMLFrame::FindFrameWithWebFrame(blink::WebFrame* web_frame) { | |
727 if (web_frame_ == web_frame) | |
728 return this; | |
729 for (HTMLFrame* child_frame : children_) { | |
730 HTMLFrame* result = child_frame->FindFrameWithWebFrame(web_frame); | |
731 if (result) | |
732 return result; | |
733 } | |
734 return nullptr; | |
735 } | |
736 | |
737 void HTMLFrame::FrameDetachedImpl(blink::WebFrame* web_frame) { | |
738 DCHECK_EQ(web_frame_, web_frame); | |
739 | |
740 while (!children_.empty()) { | |
741 HTMLFrame* child = children_.front(); | |
742 child->Close(); | |
743 DCHECK(children_.empty() || children_.front() != child); | |
744 } | |
745 | |
746 if (web_frame->parent()) | |
747 web_frame->parent()->removeChild(web_frame); | |
748 | |
749 delete this; | |
750 } | |
751 | |
752 void HTMLFrame::OnWindowBoundsChanged(mus::Window* window, | |
753 const gfx::Rect& old_bounds, | |
754 const gfx::Rect& new_bounds) { | |
755 DCHECK_EQ(window, window_); | |
756 if (html_widget_) | |
757 html_widget_->OnWindowBoundsChanged(window); | |
758 } | |
759 | |
760 void HTMLFrame::OnWindowDestroyed(mus::Window* window) { | |
761 DCHECK_EQ(window, window_); | |
762 window_->RemoveObserver(this); | |
763 window_ = nullptr; | |
764 Close(); | |
765 } | |
766 | |
767 void HTMLFrame::OnWindowFocusChanged(mus::Window* gained_focus, | |
768 mus::Window* lost_focus) { | |
769 UpdateFocus(); | |
770 } | |
771 | |
772 void HTMLFrame::OnWindowInputEvent(mus::Window* window, | |
773 mus::mojom::EventPtr event, | |
774 scoped_ptr<base::Closure>* ack_callback) { | |
775 if (event->pointer_data && event->pointer_data->location) { | |
776 // Blink expects coordintes to be in DIPs. | |
777 event->pointer_data->location->x /= global_state()->device_pixel_ratio(); | |
778 event->pointer_data->location->y /= global_state()->device_pixel_ratio(); | |
779 event->pointer_data->location->screen_x /= | |
780 global_state()->device_pixel_ratio(); | |
781 event->pointer_data->location->screen_y /= | |
782 global_state()->device_pixel_ratio(); | |
783 } | |
784 | |
785 blink::WebWidget* web_widget = GetWebWidget(); | |
786 | |
787 if (!touch_handler_ && web_widget) | |
788 touch_handler_.reset(new TouchHandler(web_widget)); | |
789 | |
790 if (touch_handler_ && | |
791 (event->action == mus::mojom::EventType::POINTER_DOWN || | |
792 event->action == mus::mojom::EventType::POINTER_UP || | |
793 event->action == mus::mojom::EventType::POINTER_CANCEL || | |
794 event->action == mus::mojom::EventType::POINTER_MOVE) && | |
795 event->pointer_data && | |
796 event->pointer_data->kind == mus::mojom::PointerKind::TOUCH) { | |
797 touch_handler_->OnTouchEvent(*event); | |
798 return; | |
799 } | |
800 | |
801 if (!web_widget) | |
802 return; | |
803 | |
804 scoped_ptr<blink::WebInputEvent> web_event = | |
805 event.To<scoped_ptr<blink::WebInputEvent>>(); | |
806 if (web_event) | |
807 web_widget->handleInputEvent(*web_event); | |
808 } | |
809 | |
810 void HTMLFrame::OnConnect( | |
811 web_view::mojom::FramePtr frame, | |
812 uint32_t change_id, | |
813 uint32_t window_id, | |
814 web_view::mojom::WindowConnectType window_connect_type, | |
815 mojo::Array<web_view::mojom::FrameDataPtr> frame_data, | |
816 int64_t navigation_start_time_ticks, | |
817 const OnConnectCallback& callback) { | |
818 // This is called if this frame is created by way of OnCreatedFrame(). | |
819 callback.Run(); | |
820 } | |
821 | |
822 void HTMLFrame::OnFrameAdded(uint32_t change_id, | |
823 web_view::mojom::FrameDataPtr frame_data) { | |
824 frame_tree_manager_->ProcessOnFrameAdded(this, change_id, | |
825 std::move(frame_data)); | |
826 } | |
827 | |
828 void HTMLFrame::OnFrameRemoved(uint32_t change_id, uint32_t frame_id) { | |
829 frame_tree_manager_->ProcessOnFrameRemoved(this, change_id, frame_id); | |
830 } | |
831 | |
832 void HTMLFrame::OnFrameClientPropertyChanged(uint32_t frame_id, | |
833 const mojo::String& name, | |
834 mojo::Array<uint8_t> new_value) { | |
835 frame_tree_manager_->ProcessOnFrameClientPropertyChanged( | |
836 this, frame_id, name, std::move(new_value)); | |
837 } | |
838 | |
839 void HTMLFrame::OnPostMessageEvent(uint32_t source_frame_id, | |
840 uint32_t target_frame_id, | |
841 HTMLMessageEventPtr serialized_event) { | |
842 NOTIMPLEMENTED(); // For message ports. | |
843 | |
844 HTMLFrame* target = frame_tree_manager_->root_->FindFrame(target_frame_id); | |
845 HTMLFrame* source = frame_tree_manager_->root_->FindFrame(source_frame_id); | |
846 if (!target || !source) { | |
847 DVLOG(1) << "Invalid source or target for PostMessage"; | |
848 return; | |
849 } | |
850 | |
851 if (!target->IsLocal()) { | |
852 DVLOG(1) << "Target for PostMessage is not lot local"; | |
853 return; | |
854 } | |
855 | |
856 blink::WebLocalFrame* target_web_frame = | |
857 target->web_frame_->toWebLocalFrame(); | |
858 | |
859 blink::WebSerializedScriptValue serialized_script_value; | |
860 serialized_script_value = blink::WebSerializedScriptValue::fromString( | |
861 serialized_event->data.To<blink::WebString>()); | |
862 | |
863 // We must pass in the target_origin to do the security check on this side, | |
864 // since it may have changed since the original postMessage call was made. | |
865 blink::WebSecurityOrigin target_origin; | |
866 if (!serialized_event->target_origin.is_null()) { | |
867 target_origin = blink::WebSecurityOrigin::createFromString( | |
868 serialized_event->target_origin.To<blink::WebString>()); | |
869 } | |
870 | |
871 // TODO(esprehn): Shouldn't this also fill in channels like RenderFrameImpl? | |
872 blink::WebMessagePortChannelArray channels; | |
873 blink::WebDOMMessageEvent msg_event(serialized_script_value, | |
874 serialized_event->source_origin.To<blink::WebString>(), | |
875 source->web_frame_, target_web_frame->document(), channels); | |
876 | |
877 target_web_frame->dispatchMessageEventWithOriginCheck(target_origin, | |
878 msg_event); | |
879 } | |
880 | |
881 void HTMLFrame::OnWillNavigate(const mojo::String& origin, | |
882 const OnWillNavigateCallback& callback) { | |
883 bool should_swap = true; | |
884 | |
885 if (this == frame_tree_manager_->local_frame_) { | |
886 HTMLFrame* new_local_frame = frame_tree_manager_->FindNewLocalFrame(); | |
887 if (!new_local_frame) { | |
888 // All local frames are descendants of |this|. In this case, the whole | |
889 // frame tree in the current process is going to be deleted very soon. We | |
890 // don't have to swap. | |
891 should_swap = false; | |
892 } else { | |
893 frame_tree_manager_->local_frame_ = new_local_frame; | |
894 } | |
895 } | |
896 | |
897 DVLOG(2) << "HTMLFrame::OnWillNavigate this=" << this << " id=" << id_ | |
898 << " local=" << IsLocal() << " should_swap=" << should_swap; | |
899 callback.Run(); | |
900 if (should_swap) { | |
901 SwapToRemote(); | |
902 const blink::WebSecurityOrigin security_origin( | |
903 blink::WebSecurityOrigin::createFromString( | |
904 blink::WebString::fromUTF8(origin))); | |
905 web_frame_->toWebRemoteFrame()->setReplicatedOrigin(security_origin); | |
906 } | |
907 } | |
908 | |
909 void HTMLFrame::OnFrameLoadingStateChanged(uint32_t frame_id, bool loading) { | |
910 HTMLFrame* frame = frame_tree_manager_->root_->FindFrame(frame_id); | |
911 // TODO(yzshen): (Apply to this method and the one below.) Is it possible that | |
912 // at this point the frame is already hosting a different document? | |
913 if (frame && !frame->IsLocal()) { | |
914 if (loading) | |
915 frame->web_frame_->toWebRemoteFrame()->didStartLoading(); | |
916 else | |
917 frame->web_frame_->toWebRemoteFrame()->didStopLoading(); | |
918 } | |
919 } | |
920 | |
921 void HTMLFrame::OnDispatchFrameLoadEvent(uint32_t frame_id) { | |
922 HTMLFrame* frame = frame_tree_manager_->root_->FindFrame(frame_id); | |
923 if (frame && !frame->IsLocal()) | |
924 frame->web_frame_->toWebRemoteFrame()->DispatchLoadEventForFrameOwner(); | |
925 } | |
926 | |
927 void HTMLFrame::Find(int32_t request_id, | |
928 const mojo::String& search_text, | |
929 web_view::mojom::FindOptionsPtr options, | |
930 bool wrap_within_frame, | |
931 const FindCallback& callback) { | |
932 blink::WebRect selection_rect; | |
933 bool result = web_frame_->toWebLocalFrame()->find( | |
934 request_id, search_text.To<blink::WebString>(), | |
935 options.To<blink::WebFindOptions>(), wrap_within_frame, &selection_rect); | |
936 | |
937 if (!result) { | |
938 // don't leave text selected as you move to the next frame. | |
939 web_frame_->executeCommand(blink::WebString::fromUTF8("Unselect"), | |
940 GetFocusedElement()); | |
941 } | |
942 | |
943 callback.Run(result); | |
944 } | |
945 | |
946 void HTMLFrame::StopFinding(bool clear_selection) { | |
947 // TODO(erg): |clear_selection| isn't correct; this should be a state enum | |
948 // that lets us STOP_FIND_ACTION_ACTIVATE_SELECTION, too. | |
949 if (clear_selection) { | |
950 blink::WebElement focused_element = GetFocusedElement(); | |
951 if (!focused_element.isNull()) { | |
952 web_frame_->executeCommand(blink::WebString::fromUTF8("Unselect"), | |
953 focused_element); | |
954 } | |
955 } | |
956 | |
957 web_frame_->toWebLocalFrame()->stopFinding(clear_selection); | |
958 } | |
959 | |
960 void HTMLFrame::HighlightFindResults(int32_t request_id, | |
961 const mojo::String& search_text, | |
962 web_view::mojom::FindOptionsPtr options, | |
963 bool reset) { | |
964 web_frame_->toWebLocalFrame()->scopeStringMatches( | |
965 request_id, search_text.To<blink::WebString>(), | |
966 options.To<blink::WebFindOptions>(), reset); | |
967 } | |
968 | |
969 void HTMLFrame::StopHighlightingFindResults() { | |
970 web_frame_->toWebLocalFrame()->resetMatchCount(); | |
971 web_frame_->toWebLocalFrame()->cancelPendingScopingEffort(); | |
972 } | |
973 | |
974 void HTMLFrame::frameDetached(blink::WebRemoteFrameClient::DetachType type) { | |
975 if (type == blink::WebRemoteFrameClient::DetachType::Swap) { | |
976 web_frame_->close(); | |
977 return; | |
978 } | |
979 | |
980 DCHECK(type == blink::WebRemoteFrameClient::DetachType::Remove); | |
981 FrameDetachedImpl(web_frame_); | |
982 } | |
983 | |
984 void HTMLFrame::postMessageEvent(blink::WebLocalFrame* source_web_frame, | |
985 blink::WebRemoteFrame* target_web_frame, | |
986 blink::WebSecurityOrigin target_origin, | |
987 blink::WebDOMMessageEvent web_event) { | |
988 NOTIMPLEMENTED(); // message_ports aren't implemented yet. | |
989 | |
990 HTMLFrame* source_frame = | |
991 frame_tree_manager_->root_->FindFrameWithWebFrame(source_web_frame); | |
992 DCHECK(source_frame); | |
993 HTMLFrame* target_frame = | |
994 frame_tree_manager_->root_->FindFrameWithWebFrame(target_web_frame); | |
995 DCHECK(target_frame); | |
996 | |
997 HTMLMessageEventPtr event(HTMLMessageEvent::New()); | |
998 event->data = mojo::Array<uint8_t>::From(web_event.data().toString()); | |
999 event->source_origin = mojo::String::From(web_event.origin()); | |
1000 if (!target_origin.isNull()) | |
1001 event->target_origin = mojo::String::From(target_origin.toString()); | |
1002 | |
1003 source_frame->server_->PostMessageEventToFrame(target_frame->id_, | |
1004 std::move(event)); | |
1005 } | |
1006 | |
1007 void HTMLFrame::initializeChildFrame(const blink::WebRect& frame_rect, | |
1008 float scale_factor) { | |
1009 // NOTE: |scale_factor| is always 1. | |
1010 const gfx::Rect rect_in_dip(frame_rect.x, frame_rect.y, frame_rect.width, | |
1011 frame_rect.height); | |
1012 const gfx::Rect rect_in_pixels(gfx::ConvertRectToPixel( | |
1013 global_state()->device_pixel_ratio(), rect_in_dip)); | |
1014 window_->SetBounds(rect_in_pixels); | |
1015 } | |
1016 | |
1017 void HTMLFrame::navigate(const blink::WebURLRequest& request, | |
1018 bool should_replace_current_entry) { | |
1019 // TODO: support |should_replace_current_entry|. | |
1020 NOTIMPLEMENTED(); // for |should_replace_current_entry | |
1021 mojo::URLRequestPtr url_request = mojo::URLRequest::From(request); | |
1022 GetServerFrame()->RequestNavigate( | |
1023 web_view::mojom::NavigationTargetType::EXISTING_FRAME, id_, | |
1024 std::move(url_request)); | |
1025 } | |
1026 | |
1027 void HTMLFrame::reload(bool ignore_cache, bool is_client_redirect) { | |
1028 NOTIMPLEMENTED(); | |
1029 } | |
1030 | |
1031 void HTMLFrame::frameRectsChanged(const blink::WebRect& frame_rect) { | |
1032 // Only the owner of window can update its size. | |
1033 if (!owned_window_) | |
1034 return; | |
1035 | |
1036 const gfx::Rect rect_in_dip(frame_rect.x, frame_rect.y, frame_rect.width, | |
1037 frame_rect.height); | |
1038 const gfx::Rect rect_in_pixels(gfx::ConvertRectToPixel( | |
1039 global_state()->device_pixel_ratio(), rect_in_dip)); | |
1040 owned_window_->window()->SetBounds(rect_in_pixels); | |
1041 | |
1042 if (!surface_layer_) | |
1043 return; | |
1044 | |
1045 surface_layer_->SetSurfaceId(cc::SurfaceId(owned_window_->window()->id()), | |
1046 global_state()->device_pixel_ratio(), | |
1047 owned_window_->window()->bounds().size()); | |
1048 } | |
1049 | |
1050 } // namespace mojo | |
OLD | NEW |