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.
5 #include "components/html_viewer/html_frame.h"
10 #include "base/bind.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_util.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "components/html_viewer/ax_provider_impl.h"
16 #include "components/html_viewer/blink_basic_type_converters.h"
17 #include "components/html_viewer/blink_input_events_type_converters.h"
18 #include "components/html_viewer/blink_text_input_type_converters.h"
19 #include "components/html_viewer/blink_url_request_type_converters.h"
20 #include "components/html_viewer/devtools_agent_impl.h"
21 #include "components/html_viewer/geolocation_client_impl.h"
22 #include "components/html_viewer/global_state.h"
23 #include "components/html_viewer/html_factory.h"
24 #include "components/html_viewer/html_frame_delegate.h"
25 #include "components/html_viewer/html_frame_properties.h"
26 #include "components/html_viewer/html_frame_tree_manager.h"
27 #include "components/html_viewer/html_widget.h"
28 #include "components/html_viewer/media_factory.h"
29 #include "components/html_viewer/stats_collection_controller.h"
30 #include "components/html_viewer/touch_handler.h"
31 #include "components/html_viewer/web_layer_impl.h"
32 #include "components/html_viewer/web_layer_tree_view_impl.h"
33 #include "components/html_viewer/web_storage_namespace_impl.h"
34 #include "components/html_viewer/web_url_loader_impl.h"
35 #include "components/mus/ids.h"
36 #include "components/mus/public/cpp/scoped_view_ptr.h"
37 #include "components/mus/public/cpp/view.h"
38 #include "components/mus/public/cpp/view_tree_connection.h"
39 #include "mojo/application/public/cpp/application_impl.h"
40 #include "mojo/application/public/cpp/connect.h"
41 #include "mojo/application/public/interfaces/shell.mojom.h"
42 #include "mojo/common/common_type_converters.h"
43 #include "mojo/converters/geometry/geometry_type_converters.h"
44 #include "skia/ext/refptr.h"
45 #include "third_party/WebKit/public/platform/Platform.h"
46 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
47 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
48 #include "third_party/WebKit/public/platform/WebSize.h"
49 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
50 #include "third_party/WebKit/public/web/WebDocument.h"
51 #include "third_party/WebKit/public/web/WebElement.h"
52 #include "third_party/WebKit/public/web/WebInputEvent.h"
53 #include "third_party/WebKit/public/web/WebKit.h"
54 #include "third_party/WebKit/public/web/WebLocalFrame.h"
55 #include "third_party/WebKit/public/web/WebNavigationPolicy.h"
56 #include "third_party/WebKit/public/web/WebRemoteFrame.h"
57 #include "third_party/WebKit/public/web/WebRemoteFrameClient.h"
58 #include "third_party/WebKit/public/web/WebScriptSource.h"
59 #include "third_party/WebKit/public/web/WebView.h"
60 #include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h"
61 #include "third_party/skia/include/core/SkCanvas.h"
62 #include "third_party/skia/include/core/SkColor.h"
63 #include "third_party/skia/include/core/SkDevice.h"
64 #include "ui/gfx/geometry/dip_util.h"
65 #include "ui/gfx/geometry/size.h"
67 #include "url/origin.h"
68 #include "url/url_constants.h"
70 using mojo::AxProvider
;
72 using mojo::ServiceProviderPtr
;
73 using mojo::URLResponsePtr
;
75 using web_view::mojom::HTMLMessageEvent
;
76 using web_view::mojom::HTMLMessageEventPtr
;
78 namespace html_viewer
{
81 const size_t kMaxTitleChars
= 4 * 1024;
83 web_view::mojom::NavigationTargetType
WebNavigationPolicyToNavigationTarget(
84 blink::WebNavigationPolicy policy
) {
86 case blink::WebNavigationPolicyCurrentTab
:
87 return web_view::mojom::NAVIGATION_TARGET_TYPE_EXISTING_FRAME
;
88 case blink::WebNavigationPolicyNewBackgroundTab
:
89 case blink::WebNavigationPolicyNewForegroundTab
:
90 case blink::WebNavigationPolicyNewWindow
:
91 case blink::WebNavigationPolicyNewPopup
:
92 return web_view::mojom::NAVIGATION_TARGET_TYPE_NEW_FRAME
;
94 return web_view::mojom::NAVIGATION_TARGET_TYPE_NO_PREFERENCE
;
98 HTMLFrame
* GetPreviousSibling(HTMLFrame
* frame
) {
99 DCHECK(frame
->parent());
100 auto iter
= std::find(frame
->parent()->children().begin(),
101 frame
->parent()->children().end(), frame
);
102 return (iter
== frame
->parent()->children().begin()) ? nullptr : *(--iter
);
107 HTMLFrame::HTMLFrame(CreateParams
* params
)
108 : frame_tree_manager_(params
->manager
),
109 parent_(params
->parent
),
113 delegate_(params
->delegate
),
114 weak_factory_(this) {
116 parent_
->children_
.push_back(this);
118 if (params
->view
&& params
->view
->id() == id_
)
119 SetView(params
->view
);
121 SetReplicatedFrameStateFromClientProperties(params
->properties
, &state_
);
124 CreateRootWebWidget();
126 // This is the root of the tree (aka the main frame).
127 // Expected order for creating webframes is:
128 // . Create local webframe (first webframe must always be local).
129 // . Set as main frame on WebView.
130 // . Swap to remote (if not local).
131 blink::WebLocalFrame
* local_web_frame
=
132 blink::WebLocalFrame::create(state_
.tree_scope
, this);
133 // We need to set the main frame before creating children so that state is
134 // properly set up in blink.
135 web_view()->setMainFrame(local_web_frame
);
137 // The resize and setDeviceScaleFactor() needs to be after setting the main
139 const gfx::Size
size_in_pixels(params
->view
->bounds().width
,
140 params
->view
->bounds().height
);
141 const gfx::Size size_in_dips
= gfx::ConvertSizeToDIP(
142 params
->view
->viewport_metrics().device_pixel_ratio
, size_in_pixels
);
143 web_view()->resize(size_in_dips
);
144 web_frame_
= local_web_frame
;
145 web_view()->setDeviceScaleFactor(global_state()->device_pixel_ratio());
146 if (id_
!= params
->view
->id()) {
147 blink::WebRemoteFrame
* remote_web_frame
=
148 blink::WebRemoteFrame::create(state_
.tree_scope
, this);
149 local_web_frame
->swap(remote_web_frame
);
150 web_frame_
= remote_web_frame
;
152 // Setup a DevTools agent if this is the local main frame and the browser
153 // side has set relevant client properties.
154 mojo::Array
<uint8_t> devtools_id
=
155 GetValueFromClientProperties("devtools-id", params
->properties
);
156 if (!devtools_id
.is_null()) {
157 mojo::Array
<uint8_t> devtools_state
=
158 GetValueFromClientProperties("devtools-state", params
->properties
);
159 std::string devtools_state_str
= devtools_state
.To
<std::string
>();
160 devtools_agent_
.reset(new DevToolsAgentImpl(
161 web_frame_
->toWebLocalFrame(), devtools_id
.To
<std::string
>(),
162 devtools_state
.is_null() ? nullptr : &devtools_state_str
));
165 // Collect startup perf data for local main frames in test environments.
166 // Child frames aren't tracked, and tracking remote frames is redundant.
167 startup_performance_data_collector_
=
168 StatsCollectionController::Install(web_frame_
, GetApp());
170 } else if (!params
->is_local_create_child
&& params
->view
&&
171 id_
== params
->view
->id()) {
172 // Frame represents the local frame, and it isn't the root of the tree.
173 HTMLFrame
* previous_sibling
= GetPreviousSibling(this);
174 blink::WebFrame
* previous_web_frame
=
175 previous_sibling
? previous_sibling
->web_frame() : nullptr;
176 CHECK(!parent_
->IsLocal());
177 web_frame_
= parent_
->web_frame()->toWebRemoteFrame()->createLocalChild(
178 state_
.tree_scope
, state_
.name
, state_
.sandbox_flags
, this,
180 CreateLocalRootWebWidget(web_frame_
->toWebLocalFrame());
181 } else if (!parent_
->IsLocal()) {
182 web_frame_
= parent_
->web_frame()->toWebRemoteFrame()->createRemoteChild(
183 state_
.tree_scope
, state_
.name
, state_
.sandbox_flags
, this);
185 CHECK(params
->is_local_create_child
);
187 blink::WebLocalFrame
* child_web_frame
=
188 blink::WebLocalFrame::create(state_
.tree_scope
, this);
189 web_frame_
= child_web_frame
;
190 parent_
->web_frame_
->appendChild(child_web_frame
);
194 blink::WebRemoteFrame
* remote_web_frame
= web_frame_
->toWebRemoteFrame();
195 if (remote_web_frame
) {
196 remote_web_frame
->setReplicatedOrigin(state_
.origin
);
197 remote_web_frame
->setReplicatedName(state_
.name
);
202 void HTMLFrame::Close() {
203 if (GetWebWidget()) {
204 // Closing the root widget (WebView) implicitly detaches. For children
205 // (which have a WebFrameWidget) a detach() is required. Use a temporary
206 // as if 'this' is the root the call to GetWebWidget()->close() deletes
208 const bool is_child
= parent_
!= nullptr;
209 GetWebWidget()->close();
211 web_frame_
->detach();
213 web_frame_
->detach();
217 const HTMLFrame
* HTMLFrame::FindFrame(uint32_t id
) const {
221 for (const HTMLFrame
* child
: children_
) {
222 const HTMLFrame
* match
= child
->FindFrame(id
);
229 blink::WebView
* HTMLFrame::web_view() {
230 blink::WebWidget
* web_widget
=
231 html_widget_
? html_widget_
->GetWidget() : nullptr;
232 return web_widget
&& web_widget
->isWebView()
233 ? static_cast<blink::WebView
*>(web_widget
)
237 blink::WebWidget
* HTMLFrame::GetWebWidget() {
238 return html_widget_
? html_widget_
->GetWidget() : nullptr;
241 bool HTMLFrame::IsLocal() const {
242 return web_frame_
->isWebLocalFrame();
245 bool HTMLFrame::HasLocalDescendant() const {
249 for (HTMLFrame
* child
: children_
) {
250 if (child
->HasLocalDescendant())
256 HTMLFrame::~HTMLFrame() {
257 DCHECK(children_
.empty());
261 std::find(parent_
->children_
.begin(), parent_
->children_
.end(), this);
262 parent_
->children_
.erase(iter
);
266 frame_tree_manager_
->OnFrameDestroyed(this);
269 delegate_
->OnFrameDestroyed();
272 view_
->RemoveObserver(this);
273 mus::ScopedViewPtr::DeleteViewOrViewManager(view_
);
277 blink::WebMediaPlayer
* HTMLFrame::createMediaPlayer(
278 blink::WebLocalFrame
* frame
,
279 const blink::WebURL
& url
,
280 blink::WebMediaPlayerClient
* client
,
281 blink::WebMediaPlayerEncryptedMediaClient
* encrypted_client
,
282 blink::WebContentDecryptionModule
* initial_cdm
) {
283 return global_state()->media_factory()->CreateMediaPlayer(
284 frame
, url
, client
, encrypted_client
, initial_cdm
, GetApp()->shell());
287 blink::WebFrame
* HTMLFrame::createChildFrame(
288 blink::WebLocalFrame
* parent
,
289 blink::WebTreeScopeType scope
,
290 const blink::WebString
& frame_name
,
291 blink::WebSandboxFlags sandbox_flags
) {
292 DCHECK(IsLocal()); // Can't create children of remote frames.
293 DCHECK_EQ(parent
, web_frame_
);
294 DCHECK(view_
); // If we're local we have to have a view.
295 // Create the view that will house the frame now. We embed once we know the
296 // url (see decidePolicyForNavigation()).
297 mus::View
* child_view
= view_
->connection()->CreateView();
298 ReplicatedFrameState child_state
;
299 child_state
.name
= frame_name
;
300 child_state
.tree_scope
= scope
;
301 child_state
.sandbox_flags
= sandbox_flags
;
302 mojo::Map
<mojo::String
, mojo::Array
<uint8_t>> client_properties
;
303 client_properties
.mark_non_null();
304 ClientPropertiesFromReplicatedFrameState(child_state
, &client_properties
);
306 child_view
->SetVisible(true);
307 view_
->AddChild(child_view
);
309 HTMLFrame::CreateParams
params(frame_tree_manager_
, this, child_view
->id(),
310 child_view
, client_properties
, nullptr);
311 params
.is_local_create_child
= true;
312 HTMLFrame
* child_frame
= GetFirstAncestorWithDelegate()
313 ->delegate_
->GetHTMLFactory()
314 ->CreateHTMLFrame(¶ms
);
315 child_frame
->owned_view_
.reset(new mus::ScopedViewPtr(child_view
));
317 web_view::mojom::FrameClientPtr client_ptr
;
318 child_frame
->frame_client_binding_
.reset(
319 new mojo::Binding
<web_view::mojom::FrameClient
>(
320 child_frame
, mojo::GetProxy(&client_ptr
)));
321 server_
->OnCreatedFrame(GetProxy(&(child_frame
->server_
)), client_ptr
.Pass(),
322 child_view
->id(), client_properties
.Pass());
323 return child_frame
->web_frame_
;
326 void HTMLFrame::frameDetached(blink::WebFrame
* web_frame
,
327 blink::WebFrameClient::DetachType type
) {
328 if (type
== blink::WebFrameClient::DetachType::Swap
) {
333 DCHECK(type
== blink::WebFrameClient::DetachType::Remove
);
334 FrameDetachedImpl(web_frame
);
337 blink::WebCookieJar
* HTMLFrame::cookieJar(blink::WebLocalFrame
* frame
) {
338 // TODO(darin): Blink does not fallback to the Platform provided WebCookieJar.
339 // Either it should, as it once did, or we should find another solution here.
340 return blink::Platform::current()->cookieJar();
343 blink::WebNavigationPolicy
HTMLFrame::decidePolicyForNavigation(
344 const NavigationPolicyInfo
& info
) {
345 // If we have extraData() it means we already have the url response
346 // (presumably because we are being called via Navigate()). In that case we
347 // can go ahead and navigate locally.
348 if (info
.urlRequest
.extraData()) {
349 DCHECK_EQ(blink::WebNavigationPolicyCurrentTab
, info
.defaultPolicy
);
350 return blink::WebNavigationPolicyCurrentTab
;
353 // about:blank is treated as the same origin and is always allowed for
355 if (parent_
&& info
.urlRequest
.url() == GURL(url::kAboutBlankURL
) &&
356 info
.defaultPolicy
== blink::WebNavigationPolicyCurrentTab
) {
357 return blink::WebNavigationPolicyCurrentTab
;
360 // Ask the Frame to handle the navigation. By returning
361 // WebNavigationPolicyIgnore the load is suppressed.
362 mojo::URLRequestPtr url_request
= mojo::URLRequest::From(info
.urlRequest
);
363 server_
->RequestNavigate(
364 WebNavigationPolicyToNavigationTarget(info
.defaultPolicy
), id_
,
367 return blink::WebNavigationPolicyIgnore
;
370 void HTMLFrame::didHandleOnloadEvents(blink::WebLocalFrame
* frame
) {
371 static bool recorded
= false;
372 if (!recorded
&& startup_performance_data_collector_
) {
373 startup_performance_data_collector_
->SetFirstWebContentsMainFrameLoadTime(
374 base::Time::Now().ToInternalValue());
379 void HTMLFrame::didAddMessageToConsole(const blink::WebConsoleMessage
& message
,
380 const blink::WebString
& source_name
,
381 unsigned source_line
,
382 const blink::WebString
& stack_trace
) {
383 VLOG(1) << "[" << source_name
.utf8() << "(" << source_line
<< ")] "
384 << message
.text
.utf8();
387 void HTMLFrame::didFinishLoad(blink::WebLocalFrame
* frame
) {
388 if (GetFirstAncestorWithDelegate() == this)
389 delegate_
->OnFrameDidFinishLoad();
392 void HTMLFrame::didNavigateWithinPage(blink::WebLocalFrame
* frame
,
393 const blink::WebHistoryItem
& history_item
,
394 blink::WebHistoryCommitType commit_type
) {
395 server_
->DidNavigateLocally(history_item
.urlString().utf8());
398 blink::WebGeolocationClient
* HTMLFrame::geolocationClient() {
399 if (!geolocation_client_impl_
)
400 geolocation_client_impl_
.reset(new GeolocationClientImpl
);
401 return geolocation_client_impl_
.get();
404 blink::WebEncryptedMediaClient
* HTMLFrame::encryptedMediaClient() {
405 return global_state()->media_factory()->GetEncryptedMediaClient();
408 void HTMLFrame::didStartLoading(bool to_different_document
) {
409 server_
->LoadingStateChanged(true, 0.0);
412 void HTMLFrame::didStopLoading() {
413 server_
->LoadingStateChanged(false, 1.0);
416 void HTMLFrame::didChangeLoadProgress(double load_progress
) {
417 server_
->LoadingStateChanged(true, load_progress
);
420 void HTMLFrame::dispatchLoad() {
421 // According to comments of WebFrameClient::dispatchLoad(), this should only
422 // be called when the parent frame is remote.
423 DCHECK(parent_
&& !parent_
->IsLocal());
424 server_
->DispatchLoadEventToParent();
427 void HTMLFrame::didChangeName(blink::WebLocalFrame
* frame
,
428 const blink::WebString
& name
) {
430 server_
->SetClientProperty(kPropertyFrameName
,
431 FrameNameToClientProperty(name
));
434 void HTMLFrame::didCommitProvisionalLoad(
435 blink::WebLocalFrame
* frame
,
436 const blink::WebHistoryItem
& item
,
437 blink::WebHistoryCommitType commit_type
) {
438 state_
.origin
= FrameOrigin(frame
);
439 server_
->SetClientProperty(kPropertyFrameOrigin
,
440 FrameOriginToClientProperty(frame
));
442 // TODO(erg): We need to pass way more information from here through to the
443 // other side. See FrameHostMsg_DidCommitProvisionalLoad_Params. It is a grab
444 // bag of everything and it looks like a combination of
445 // NavigatorImpl::DidNavigate and
446 // NavigationControllerImpl::RendererDidNavigate use everything passed
448 server_
->DidCommitProvisionalLoad();
451 void HTMLFrame::didReceiveTitle(blink::WebLocalFrame
* frame
,
452 const blink::WebString
& title
,
453 blink::WebTextDirection direction
) {
454 // TODO(beng): handle |direction|.
455 mojo::String formatted
;
456 if (!title
.isNull()) {
458 mojo::String::From(base::string16(title
).substr(0, kMaxTitleChars
));
460 server_
->TitleChanged(formatted
);
463 void HTMLFrame::Bind(
464 web_view::mojom::FramePtr frame
,
465 mojo::InterfaceRequest
<web_view::mojom::FrameClient
> frame_client_request
) {
467 server_
= frame
.Pass();
468 server_
.set_connection_error_handler(
469 base::Bind(&HTMLFrame::Close
, base::Unretained(this)));
470 frame_client_binding_
.reset(new mojo::Binding
<web_view::mojom::FrameClient
>(
471 this, frame_client_request
.Pass()));
474 void HTMLFrame::SetValueFromClientProperty(const std::string
& name
,
475 mojo::Array
<uint8_t> new_data
) {
479 // Only the name and origin dynamically change.
480 if (name
== kPropertyFrameOrigin
) {
481 state_
.origin
= FrameOriginFromClientProperty(new_data
);
482 web_frame_
->toWebRemoteFrame()->setReplicatedOrigin(state_
.origin
);
483 } else if (name
== kPropertyFrameName
) {
484 state_
.name
= FrameNameFromClientProperty(new_data
);
485 web_frame_
->toWebRemoteFrame()->setReplicatedName(state_
.name
);
489 HTMLFrame
* HTMLFrame::GetFirstAncestorWithDelegate() {
490 HTMLFrame
* frame
= this;
491 while (frame
&& !frame
->delegate_
)
492 frame
= frame
->parent_
;
496 mojo::ApplicationImpl
* HTMLFrame::GetApp() {
497 return GetFirstAncestorWithDelegate()->delegate_
->GetApp();
500 web_view::mojom::Frame
* HTMLFrame::GetServerFrame() {
501 // Prefer an ancestor with a server Frame.
502 for (HTMLFrame
* frame
= this; frame
; frame
= frame
->parent_
) {
503 if (frame
->server_
.get())
504 return frame
->server_
.get();
507 // No local root. This means we're a remote frame with no local frame
508 // ancestors. Use the server Frame from the local root of the
509 // HTMLFrameTreeManager.
510 return frame_tree_manager_
->local_root_
->server_
.get();
513 void HTMLFrame::SetView(mus::View
* view
) {
515 view_
->RemoveObserver(this);
518 view_
->AddObserver(this);
521 void HTMLFrame::CreateRootWebWidget() {
522 DCHECK(!html_widget_
);
524 HTMLWidgetRootLocal::CreateParams
create_params(GetApp(), global_state(),
527 delegate_
->GetHTMLFactory()->CreateHTMLWidgetRootLocal(&create_params
));
529 html_widget_
.reset(new HTMLWidgetRootRemote
);
533 void HTMLFrame::CreateLocalRootWebWidget(blink::WebLocalFrame
* local_frame
) {
534 DCHECK(!html_widget_
);
537 new HTMLWidgetLocalRoot(GetApp(), global_state(), view_
, local_frame
));
540 void HTMLFrame::UpdateFocus() {
541 blink::WebWidget
* web_widget
= GetWebWidget();
542 if (!web_widget
|| !view_
)
544 const bool is_focused
= view_
&& view_
->HasFocus();
545 web_widget
->setFocus(is_focused
);
546 if (web_widget
->isWebView())
547 static_cast<blink::WebView
*>(web_widget
)->setIsActive(is_focused
);
550 void HTMLFrame::SwapToRemote() {
553 HTMLFrameDelegate
* delegate
= delegate_
;
556 blink::WebRemoteFrame
* remote_frame
=
557 blink::WebRemoteFrame::create(state_
.tree_scope
, this);
558 remote_frame
->initializeFromFrame(web_frame_
->toWebLocalFrame());
559 // swap() ends up calling us back and we then close the frame, which deletes
561 web_frame_
->swap(remote_frame
);
562 // TODO(sky): this isn't quite right, but WebLayerImpl is temporary.
565 new WebLayerImpl(owned_view_
->view(),
566 global_state()->device_pixel_ratio()));
568 remote_frame
->setRemoteWebLayer(web_layer_
.get());
569 remote_frame
->setReplicatedName(state_
.name
);
570 remote_frame
->setReplicatedOrigin(state_
.origin
);
571 remote_frame
->setReplicatedSandboxFlags(state_
.sandbox_flags
);
572 // Tell the frame that it is actually loading. This prevents its parent
573 // from prematurely dispatching load event.
574 remote_frame
->didStartLoading();
575 web_frame_
= remote_frame
;
578 frame_client_binding_
.reset();
580 delegate
->OnFrameSwappedToRemote();
583 void HTMLFrame::SwapToLocal(
584 HTMLFrameDelegate
* delegate
,
586 const mojo::Map
<mojo::String
, mojo::Array
<uint8_t>>& properties
) {
588 // It doesn't make sense for the root to swap to local.
590 delegate_
= delegate
;
592 SetReplicatedFrameStateFromClientProperties(properties
, &state_
);
593 blink::WebLocalFrame
* local_web_frame
=
594 blink::WebLocalFrame::create(state_
.tree_scope
, this);
595 local_web_frame
->initializeToReplaceRemoteFrame(
596 web_frame_
->toWebRemoteFrame(), state_
.name
, state_
.sandbox_flags
);
597 // The swap() ends up calling to frameDetached() and deleting the old.
598 web_frame_
->swap(local_web_frame
);
599 web_frame_
= local_web_frame
;
604 void HTMLFrame::SwapDelegate(HTMLFrameDelegate
* delegate
) {
606 HTMLFrameDelegate
* old_delegate
= delegate_
;
607 delegate_
= delegate
;
608 delegate
->OnSwap(this, old_delegate
);
611 HTMLFrame
* HTMLFrame::FindFrameWithWebFrame(blink::WebFrame
* web_frame
) {
612 if (web_frame_
== web_frame
)
614 for (HTMLFrame
* child_frame
: children_
) {
615 HTMLFrame
* result
= child_frame
->FindFrameWithWebFrame(web_frame
);
622 void HTMLFrame::FrameDetachedImpl(blink::WebFrame
* web_frame
) {
623 DCHECK_EQ(web_frame_
, web_frame
);
625 while (!children_
.empty()) {
626 HTMLFrame
* child
= children_
.front();
628 DCHECK(children_
.empty() || children_
.front() != child
);
631 if (web_frame
->parent())
632 web_frame
->parent()->removeChild(web_frame
);
637 void HTMLFrame::OnViewBoundsChanged(View
* view
,
638 const Rect
& old_bounds
,
639 const Rect
& new_bounds
) {
640 DCHECK_EQ(view
, view_
);
642 html_widget_
->OnViewBoundsChanged(view
);
645 void HTMLFrame::OnViewDestroyed(View
* view
) {
646 DCHECK_EQ(view
, view_
);
647 view_
->RemoveObserver(this);
652 void HTMLFrame::OnViewInputEvent(View
* view
, const mojo::EventPtr
& event
) {
653 if (event
->pointer_data
) {
654 // Blink expects coordintes to be in DIPs.
655 event
->pointer_data
->location
->x
/= global_state()->device_pixel_ratio();
656 event
->pointer_data
->location
->y
/= global_state()->device_pixel_ratio();
657 event
->pointer_data
->location
->screen_x
/=
658 global_state()->device_pixel_ratio();
659 event
->pointer_data
->location
->screen_y
/=
660 global_state()->device_pixel_ratio();
663 blink::WebWidget
* web_widget
= GetWebWidget();
665 if (!touch_handler_
&& web_widget
)
666 touch_handler_
.reset(new TouchHandler(web_widget
));
668 if (touch_handler_
&& (event
->action
== mojo::EVENT_TYPE_POINTER_DOWN
||
669 event
->action
== mojo::EVENT_TYPE_POINTER_UP
||
670 event
->action
== mojo::EVENT_TYPE_POINTER_CANCEL
||
671 event
->action
== mojo::EVENT_TYPE_POINTER_MOVE
) &&
672 event
->pointer_data
->kind
== mojo::POINTER_KIND_TOUCH
) {
673 touch_handler_
->OnTouchEvent(*event
);
680 scoped_ptr
<blink::WebInputEvent
> web_event
=
681 event
.To
<scoped_ptr
<blink::WebInputEvent
>>();
683 web_widget
->handleInputEvent(*web_event
);
686 void HTMLFrame::OnViewFocusChanged(mus::View
* gained_focus
,
687 mus::View
* lost_focus
) {
691 void HTMLFrame::OnConnect(web_view::mojom::FramePtr frame
,
694 web_view::mojom::ViewConnectType view_connect_type
,
695 mojo::Array
<web_view::mojom::FrameDataPtr
> frame_data
,
696 const OnConnectCallback
& callback
) {
697 // This is called if this frame is created by way of OnCreatedFrame().
701 void HTMLFrame::OnFrameAdded(uint32_t change_id
,
702 web_view::mojom::FrameDataPtr frame_data
) {
703 frame_tree_manager_
->ProcessOnFrameAdded(this, change_id
, frame_data
.Pass());
706 void HTMLFrame::OnFrameRemoved(uint32_t change_id
, uint32_t frame_id
) {
707 frame_tree_manager_
->ProcessOnFrameRemoved(this, change_id
, frame_id
);
710 void HTMLFrame::OnFrameClientPropertyChanged(uint32_t frame_id
,
711 const mojo::String
& name
,
712 mojo::Array
<uint8_t> new_value
) {
713 frame_tree_manager_
->ProcessOnFrameClientPropertyChanged(this, frame_id
, name
,
717 void HTMLFrame::OnPostMessageEvent(uint32_t source_frame_id
,
718 uint32_t target_frame_id
,
719 HTMLMessageEventPtr serialized_event
) {
720 NOTIMPLEMENTED(); // For message ports.
722 HTMLFrame
* target
= frame_tree_manager_
->root_
->FindFrame(target_frame_id
);
723 HTMLFrame
* source
= frame_tree_manager_
->root_
->FindFrame(source_frame_id
);
724 if (!target
|| !source
) {
725 DVLOG(1) << "Invalid source or target for PostMessage";
729 if (!target
->IsLocal()) {
730 DVLOG(1) << "Target for PostMessage is not lot local";
734 blink::WebLocalFrame
* target_web_frame
=
735 target
->web_frame_
->toWebLocalFrame();
737 blink::WebSerializedScriptValue serialized_script_value
;
738 serialized_script_value
= blink::WebSerializedScriptValue::fromString(
739 serialized_event
->data
.To
<blink::WebString
>());
741 blink::WebMessagePortChannelArray channels
;
743 // Create an event with the message. The next-to-last parameter to
744 // initMessageEvent is the last event ID, which is not used with postMessage.
745 blink::WebDOMEvent event
=
746 target_web_frame
->document().createEvent("MessageEvent");
747 blink::WebDOMMessageEvent msg_event
= event
.to
<blink::WebDOMMessageEvent
>();
748 msg_event
.initMessageEvent(
750 // |canBubble| and |cancellable| are always false
751 false, false, serialized_script_value
,
752 serialized_event
->source_origin
.To
<blink::WebString
>(),
753 source
->web_frame_
, target_web_frame
->document(), "", channels
);
755 // We must pass in the target_origin to do the security check on this side,
756 // since it may have changed since the original postMessage call was made.
757 blink::WebSecurityOrigin target_origin
;
758 if (!serialized_event
->target_origin
.is_null()) {
759 target_origin
= blink::WebSecurityOrigin::createFromString(
760 serialized_event
->target_origin
.To
<blink::WebString
>());
762 target_web_frame
->dispatchMessageEventWithOriginCheck(target_origin
,
766 void HTMLFrame::OnWillNavigate() {
767 if (IsLocal() && this != frame_tree_manager_
->local_root_
)
771 void HTMLFrame::OnFrameLoadingStateChanged(uint32_t frame_id
, bool loading
) {
772 HTMLFrame
* frame
= frame_tree_manager_
->root_
->FindFrame(frame_id
);
773 // TODO(yzshen): (Apply to this method and the one below.) Is it possible that
774 // at this point the frame is already hosting a different document?
775 if (frame
&& !frame
->IsLocal()) {
777 frame
->web_frame_
->toWebRemoteFrame()->didStartLoading();
779 frame
->web_frame_
->toWebRemoteFrame()->didStopLoading();
783 void HTMLFrame::OnDispatchFrameLoadEvent(uint32_t frame_id
) {
784 HTMLFrame
* frame
= frame_tree_manager_
->root_
->FindFrame(frame_id
);
785 if (frame
&& !frame
->IsLocal())
786 frame
->web_frame_
->toWebRemoteFrame()->DispatchLoadEventForFrameOwner();
789 void HTMLFrame::frameDetached(blink::WebRemoteFrameClient::DetachType type
) {
790 if (type
== blink::WebRemoteFrameClient::DetachType::Swap
) {
795 DCHECK(type
== blink::WebRemoteFrameClient::DetachType::Remove
);
796 FrameDetachedImpl(web_frame_
);
799 void HTMLFrame::postMessageEvent(blink::WebLocalFrame
* source_web_frame
,
800 blink::WebRemoteFrame
* target_web_frame
,
801 blink::WebSecurityOrigin target_origin
,
802 blink::WebDOMMessageEvent web_event
) {
803 NOTIMPLEMENTED(); // message_ports aren't implemented yet.
805 HTMLFrame
* source_frame
=
806 frame_tree_manager_
->root_
->FindFrameWithWebFrame(source_web_frame
);
807 DCHECK(source_frame
);
808 HTMLFrame
* target_frame
=
809 frame_tree_manager_
->root_
->FindFrameWithWebFrame(target_web_frame
);
810 DCHECK(target_frame
);
812 HTMLMessageEventPtr
event(HTMLMessageEvent::New());
813 event
->data
= mojo::Array
<uint8_t>::From(web_event
.data().toString());
814 event
->source_origin
= mojo::String::From(web_event
.origin());
815 if (!target_origin
.isNull())
816 event
->target_origin
= mojo::String::From(target_origin
.toString());
818 source_frame
->server_
->PostMessageEventToFrame(target_frame
->id_
,
822 void HTMLFrame::initializeChildFrame(const blink::WebRect
& frame_rect
,
823 float scale_factor
) {
824 // NOTE: |scale_factor| is always 1.
825 const gfx::Rect
rect_in_dip(frame_rect
.x
, frame_rect
.y
, frame_rect
.width
,
827 const gfx::Rect
rect_in_pixels(gfx::ConvertRectToPixel(
828 global_state()->device_pixel_ratio(), rect_in_dip
));
829 const mojo::RectPtr
mojo_rect_in_pixels(mojo::Rect::From(rect_in_pixels
));
830 view_
->SetBounds(*mojo_rect_in_pixels
);
833 void HTMLFrame::navigate(const blink::WebURLRequest
& request
,
834 bool should_replace_current_entry
) {
835 // TODO: support |should_replace_current_entry|.
836 NOTIMPLEMENTED(); // for |should_replace_current_entry
837 mojo::URLRequestPtr url_request
= mojo::URLRequest::From(request
);
838 GetServerFrame()->RequestNavigate(
839 web_view::mojom::NAVIGATION_TARGET_TYPE_EXISTING_FRAME
, id_
,
843 void HTMLFrame::reload(bool ignore_cache
, bool is_client_redirect
) {
847 void HTMLFrame::forwardInputEvent(const blink::WebInputEvent
* event
) {