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/view_manager/ids.h"
36 #include "components/view_manager/public/cpp/scoped_view_ptr.h"
37 #include "components/view_manager/public/cpp/view.h"
38 #include "components/view_manager/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"
66 #include "url/origin.h"
68 using mojo::AxProvider
;
70 using mojo::ServiceProviderPtr
;
71 using mojo::URLResponsePtr
;
73 using web_view::HTMLMessageEvent
;
74 using web_view::HTMLMessageEventPtr
;
76 namespace html_viewer
{
79 const size_t kMaxTitleChars
= 4 * 1024;
81 web_view::NavigationTargetType
WebNavigationPolicyToNavigationTarget(
82 blink::WebNavigationPolicy policy
) {
84 case blink::WebNavigationPolicyCurrentTab
:
85 return web_view::NAVIGATION_TARGET_TYPE_EXISTING_FRAME
;
86 case blink::WebNavigationPolicyNewBackgroundTab
:
87 case blink::WebNavigationPolicyNewForegroundTab
:
88 case blink::WebNavigationPolicyNewWindow
:
89 case blink::WebNavigationPolicyNewPopup
:
90 return web_view::NAVIGATION_TARGET_TYPE_NEW_FRAME
;
92 return web_view::NAVIGATION_TARGET_TYPE_NO_PREFERENCE
;
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
);
105 HTMLFrame::HTMLFrame(CreateParams
* params
)
106 : frame_tree_manager_(params
->manager
),
107 parent_(params
->parent
),
111 delegate_(params
->delegate
),
112 weak_factory_(this) {
114 parent_
->children_
.push_back(this);
116 if (params
->view
&& params
->view
->id() == id_
)
117 SetView(params
->view
);
119 SetReplicatedFrameStateFromClientProperties(params
->properties
, &state_
);
122 CreateRootWebWidget();
124 // This is the root of the tree (aka the main frame).
125 // Expected order for creating webframes is:
126 // . Create local webframe (first webframe must always be local).
127 // . Set as main frame on WebView.
128 // . Swap to remote (if not local).
129 blink::WebLocalFrame
* local_web_frame
=
130 blink::WebLocalFrame::create(state_
.tree_scope
, this);
131 // We need to set the main frame before creating children so that state is
132 // properly set up in blink.
133 web_view()->setMainFrame(local_web_frame
);
135 // The resize and setDeviceScaleFactor() needs to be after setting the main
137 const gfx::Size
size_in_pixels(params
->view
->bounds().width
,
138 params
->view
->bounds().height
);
139 const gfx::Size size_in_dips
= gfx::ConvertSizeToDIP(
140 params
->view
->viewport_metrics().device_pixel_ratio
, size_in_pixels
);
141 web_view()->resize(size_in_dips
);
142 web_frame_
= local_web_frame
;
143 web_view()->setDeviceScaleFactor(global_state()->device_pixel_ratio());
144 if (id_
!= params
->view
->id()) {
145 blink::WebRemoteFrame
* remote_web_frame
=
146 blink::WebRemoteFrame::create(state_
.tree_scope
, this);
147 local_web_frame
->swap(remote_web_frame
);
148 web_frame_
= remote_web_frame
;
150 // Setup a DevTools agent if this is the local main frame and the browser
151 // side has set relevant client properties.
152 mojo::Array
<uint8_t> devtools_id
=
153 GetValueFromClientProperties("devtools-id", params
->properties
);
154 if (!devtools_id
.is_null()) {
155 mojo::Array
<uint8_t> devtools_state
=
156 GetValueFromClientProperties("devtools-state", params
->properties
);
157 std::string devtools_state_str
= devtools_state
.To
<std::string
>();
158 devtools_agent_
.reset(new DevToolsAgentImpl(
159 web_frame_
->toWebLocalFrame(), devtools_id
.To
<std::string
>(),
160 devtools_state
.is_null() ? nullptr : &devtools_state_str
));
163 // Collect startup perf data for local main frames in test environments.
164 // Child frames aren't tracked, and tracking remote frames is redundant.
165 startup_performance_data_collector_
=
166 StatsCollectionController::Install(web_frame_
, GetLocalRootApp());
168 } else if (!params
->allow_local_shared_frame
&& params
->view
&&
169 id_
== params
->view
->id()) {
170 // Frame represents the local frame, and it isn't the root of the tree.
171 HTMLFrame
* previous_sibling
= GetPreviousSibling(this);
172 blink::WebFrame
* previous_web_frame
=
173 previous_sibling
? previous_sibling
->web_frame() : nullptr;
174 CHECK(!parent_
->IsLocal());
175 web_frame_
= parent_
->web_frame()->toWebRemoteFrame()->createLocalChild(
176 state_
.tree_scope
, state_
.name
, state_
.sandbox_flags
, this,
178 CreateLocalRootWebWidget(web_frame_
->toWebLocalFrame());
179 } else if (!parent_
->IsLocal()) {
180 web_frame_
= parent_
->web_frame()->toWebRemoteFrame()->createRemoteChild(
181 state_
.tree_scope
, state_
.name
, state_
.sandbox_flags
, this);
183 // TODO(sky): this DCHECK, and |allow_local_shared_frame| should be
184 // moved to HTMLFrameTreeManager. It makes more sense there.
185 // This should never happen (if we create a local child we don't call
186 // Init(), and the frame server should not being creating child frames of
188 DCHECK(params
->allow_local_shared_frame
);
190 blink::WebLocalFrame
* child_web_frame
=
191 blink::WebLocalFrame::create(state_
.tree_scope
, this);
192 web_frame_
= child_web_frame
;
193 parent_
->web_frame_
->appendChild(child_web_frame
);
197 blink::WebRemoteFrame
* remote_web_frame
= web_frame_
->toWebRemoteFrame();
198 if (remote_web_frame
) {
199 remote_web_frame
->setReplicatedOrigin(state_
.origin
);
200 remote_web_frame
->setReplicatedName(state_
.name
);
205 void HTMLFrame::Close() {
206 if (GetWebWidget()) {
207 // Closing the root widget (WebView) implicitly detaches. For children
208 // (which have a WebFrameWidget) a detach() is required. Use a temporary
209 // as if 'this' is the root the call to GetWebWidget()->close() deletes
211 const bool is_child
= parent_
!= nullptr;
212 GetWebWidget()->close();
214 web_frame_
->detach();
216 web_frame_
->detach();
220 const HTMLFrame
* HTMLFrame::FindFrame(uint32_t id
) const {
224 for (const HTMLFrame
* child
: children_
) {
225 const HTMLFrame
* match
= child
->FindFrame(id
);
232 blink::WebView
* HTMLFrame::web_view() {
233 blink::WebWidget
* web_widget
=
234 html_widget_
? html_widget_
->GetWidget() : nullptr;
235 return web_widget
&& web_widget
->isWebView()
236 ? static_cast<blink::WebView
*>(web_widget
)
240 blink::WebWidget
* HTMLFrame::GetWebWidget() {
241 return html_widget_
? html_widget_
->GetWidget() : nullptr;
244 bool HTMLFrame::IsLocal() const {
245 return web_frame_
->isWebLocalFrame();
248 bool HTMLFrame::HasLocalDescendant() const {
252 for (HTMLFrame
* child
: children_
) {
253 if (child
->HasLocalDescendant())
259 HTMLFrame::~HTMLFrame() {
260 DCHECK(children_
.empty());
264 std::find(parent_
->children_
.begin(), parent_
->children_
.end(), this);
265 parent_
->children_
.erase(iter
);
269 frame_tree_manager_
->OnFrameDestroyed(this);
272 delegate_
->OnFrameDestroyed();
275 view_
->RemoveObserver(this);
276 mojo::ScopedViewPtr::DeleteViewOrViewManager(view_
);
280 void HTMLFrame::Bind(web_view::FrameTreeServerPtr frame_tree_server
,
281 mojo::InterfaceRequest
<web_view::FrameTreeClient
>
282 frame_tree_client_request
) {
284 // TODO(sky): error handling.
285 server_
= frame_tree_server
.Pass();
286 frame_tree_client_binding_
.reset(new mojo::Binding
<web_view::FrameTreeClient
>(
287 this, frame_tree_client_request
.Pass()));
290 void HTMLFrame::SetValueFromClientProperty(const std::string
& name
,
291 mojo::Array
<uint8_t> new_data
) {
295 // Only the name and origin dynamically change.
296 if (name
== kPropertyFrameOrigin
) {
297 state_
.origin
= FrameOriginFromClientProperty(new_data
);
298 web_frame_
->toWebRemoteFrame()->setReplicatedOrigin(state_
.origin
);
299 } else if (name
== kPropertyFrameName
) {
300 state_
.name
= FrameNameFromClientProperty(new_data
);
301 web_frame_
->toWebRemoteFrame()->setReplicatedName(state_
.name
);
305 HTMLFrame
* HTMLFrame::GetLocalRoot() {
306 HTMLFrame
* frame
= this;
307 while (frame
&& !frame
->delegate_
)
308 frame
= frame
->parent_
;
312 mojo::ApplicationImpl
* HTMLFrame::GetLocalRootApp() {
313 return GetLocalRoot()->delegate_
->GetApp();
316 web_view::FrameTreeServer
* HTMLFrame::GetFrameTreeServer() {
317 // Prefer the local root.
318 HTMLFrame
* local_root
= GetLocalRoot();
320 return local_root
->server_
.get();
322 // No local root. This means we're a remote frame with no local frame
323 // ancestors. Use the local frame from the FrameTreeServer.
324 return frame_tree_manager_
->local_root_
->server_
.get();
327 void HTMLFrame::SetView(mojo::View
* view
) {
329 view_
->RemoveObserver(this);
332 view_
->AddObserver(this);
335 void HTMLFrame::CreateRootWebWidget() {
336 DCHECK(!html_widget_
);
338 HTMLWidgetRootLocal::CreateParams
create_params(GetLocalRootApp(),
339 global_state(), view_
);
341 delegate_
->GetHTMLFactory()->CreateHTMLWidgetRootLocal(&create_params
));
343 html_widget_
.reset(new HTMLWidgetRootRemote
);
347 void HTMLFrame::CreateLocalRootWebWidget(blink::WebLocalFrame
* local_frame
) {
348 DCHECK(!html_widget_
);
350 html_widget_
.reset(new HTMLWidgetLocalRoot(GetLocalRootApp(), global_state(),
351 view_
, local_frame
));
354 void HTMLFrame::UpdateFocus() {
355 blink::WebWidget
* web_widget
= GetWebWidget();
356 if (!web_widget
|| !view_
)
358 const bool is_focused
= view_
&& view_
->HasFocus();
359 web_widget
->setFocus(is_focused
);
360 if (web_widget
->isWebView())
361 static_cast<blink::WebView
*>(web_widget
)->setIsActive(is_focused
);
364 void HTMLFrame::SwapToRemote() {
367 HTMLFrameDelegate
* delegate
= delegate_
;
370 blink::WebRemoteFrame
* remote_frame
=
371 blink::WebRemoteFrame::create(state_
.tree_scope
, this);
372 remote_frame
->initializeFromFrame(web_frame_
->toWebLocalFrame());
373 // swap() ends up calling us back and we then close the frame, which deletes
375 web_frame_
->swap(remote_frame
);
376 // TODO(sky): this isn't quite right, but WebLayerImpl is temporary.
379 new WebLayerImpl(owned_view_
->view(),
380 global_state()->device_pixel_ratio()));
382 remote_frame
->setRemoteWebLayer(web_layer_
.get());
383 remote_frame
->setReplicatedName(state_
.name
);
384 remote_frame
->setReplicatedOrigin(state_
.origin
);
385 remote_frame
->setReplicatedSandboxFlags(state_
.sandbox_flags
);
386 web_frame_
= remote_frame
;
389 delegate
->OnFrameSwappedToRemote();
392 void HTMLFrame::SwapToLocal(
393 HTMLFrameDelegate
* delegate
,
395 const mojo::Map
<mojo::String
, mojo::Array
<uint8_t>>& properties
) {
397 // It doesn't make sense for the root to swap to local.
399 delegate_
= delegate
;
401 SetReplicatedFrameStateFromClientProperties(properties
, &state_
);
402 blink::WebLocalFrame
* local_web_frame
=
403 blink::WebLocalFrame::create(state_
.tree_scope
, this);
404 local_web_frame
->initializeToReplaceRemoteFrame(
405 web_frame_
->toWebRemoteFrame(), state_
.name
, state_
.sandbox_flags
);
406 // The swap() ends up calling to frameDetached() and deleting the old.
407 web_frame_
->swap(local_web_frame
);
408 web_frame_
= local_web_frame
;
413 void HTMLFrame::SwapDelegate(HTMLFrameDelegate
* delegate
) {
415 HTMLFrameDelegate
* old_delegate
= delegate_
;
416 delegate_
= delegate
;
417 delegate
->OnSwap(this, old_delegate
);
420 HTMLFrame
* HTMLFrame::FindFrameWithWebFrame(blink::WebFrame
* web_frame
) {
421 if (web_frame_
== web_frame
)
423 for (HTMLFrame
* child_frame
: children_
) {
424 HTMLFrame
* result
= child_frame
->FindFrameWithWebFrame(web_frame
);
431 void HTMLFrame::FrameDetachedImpl(blink::WebFrame
* web_frame
) {
432 DCHECK_EQ(web_frame_
, web_frame
);
434 while (!children_
.empty()) {
435 HTMLFrame
* child
= children_
.front();
437 DCHECK(children_
.empty() || children_
.front() != child
);
440 if (web_frame
->parent())
441 web_frame
->parent()->removeChild(web_frame
);
446 void HTMLFrame::OnViewBoundsChanged(View
* view
,
447 const Rect
& old_bounds
,
448 const Rect
& new_bounds
) {
449 DCHECK_EQ(view
, view_
);
451 html_widget_
->OnViewBoundsChanged(view
);
454 void HTMLFrame::OnViewDestroyed(View
* view
) {
455 DCHECK_EQ(view
, view_
);
456 view_
->RemoveObserver(this);
461 void HTMLFrame::OnViewInputEvent(View
* view
, const mojo::EventPtr
& event
) {
462 if (event
->pointer_data
) {
463 // Blink expects coordintes to be in DIPs.
464 event
->pointer_data
->x
/= global_state()->device_pixel_ratio();
465 event
->pointer_data
->y
/= global_state()->device_pixel_ratio();
466 event
->pointer_data
->screen_x
/= global_state()->device_pixel_ratio();
467 event
->pointer_data
->screen_y
/= global_state()->device_pixel_ratio();
470 blink::WebWidget
* web_widget
= GetWebWidget();
472 if (!touch_handler_
&& web_widget
)
473 touch_handler_
.reset(new TouchHandler(web_widget
));
475 if (touch_handler_
&& (event
->action
== mojo::EVENT_TYPE_POINTER_DOWN
||
476 event
->action
== mojo::EVENT_TYPE_POINTER_UP
||
477 event
->action
== mojo::EVENT_TYPE_POINTER_CANCEL
||
478 event
->action
== mojo::EVENT_TYPE_POINTER_MOVE
) &&
479 event
->pointer_data
->kind
== mojo::POINTER_KIND_TOUCH
) {
480 touch_handler_
->OnTouchEvent(*event
);
487 scoped_ptr
<blink::WebInputEvent
> web_event
=
488 event
.To
<scoped_ptr
<blink::WebInputEvent
>>();
490 web_widget
->handleInputEvent(*web_event
);
493 void HTMLFrame::OnViewFocusChanged(mojo::View
* gained_focus
,
494 mojo::View
* lost_focus
) {
498 void HTMLFrame::OnConnect(web_view::FrameTreeServerPtr server
,
501 web_view::ViewConnectType view_connect_type
,
502 mojo::Array
<web_view::FrameDataPtr
> frame_data
,
503 const OnConnectCallback
& callback
) {
504 // OnConnect() is only sent once, and has been received (by
505 // DocumentResourceWaiter) by the time we get here.
509 void HTMLFrame::OnFrameAdded(uint32_t change_id
,
510 web_view::FrameDataPtr frame_data
) {
511 frame_tree_manager_
->ProcessOnFrameAdded(this, change_id
, frame_data
.Pass());
514 void HTMLFrame::OnFrameRemoved(uint32_t change_id
, uint32_t frame_id
) {
515 frame_tree_manager_
->ProcessOnFrameRemoved(this, change_id
, frame_id
);
518 void HTMLFrame::OnFrameClientPropertyChanged(uint32_t frame_id
,
519 const mojo::String
& name
,
520 mojo::Array
<uint8_t> new_value
) {
521 frame_tree_manager_
->ProcessOnFrameClientPropertyChanged(this, frame_id
, name
,
525 void HTMLFrame::OnPostMessageEvent(uint32_t source_frame_id
,
526 uint32_t target_frame_id
,
527 HTMLMessageEventPtr serialized_event
) {
528 NOTIMPLEMENTED(); // For message ports.
530 HTMLFrame
* target
= frame_tree_manager_
->root_
->FindFrame(target_frame_id
);
531 HTMLFrame
* source
= frame_tree_manager_
->root_
->FindFrame(source_frame_id
);
532 if (!target
|| !source
) {
533 DVLOG(1) << "Invalid source or target for PostMessage";
537 if (!target
->IsLocal()) {
538 DVLOG(1) << "Target for PostMessage is not lot local";
542 blink::WebLocalFrame
* target_web_frame
=
543 target
->web_frame_
->toWebLocalFrame();
545 blink::WebSerializedScriptValue serialized_script_value
;
546 serialized_script_value
= blink::WebSerializedScriptValue::fromString(
547 serialized_event
->data
.To
<blink::WebString
>());
549 blink::WebMessagePortChannelArray channels
;
551 // Create an event with the message. The next-to-last parameter to
552 // initMessageEvent is the last event ID, which is not used with postMessage.
553 blink::WebDOMEvent event
=
554 target_web_frame
->document().createEvent("MessageEvent");
555 blink::WebDOMMessageEvent msg_event
= event
.to
<blink::WebDOMMessageEvent
>();
556 msg_event
.initMessageEvent(
558 // |canBubble| and |cancellable| are always false
559 false, false, serialized_script_value
,
560 serialized_event
->source_origin
.To
<blink::WebString
>(),
561 source
->web_frame_
, target_web_frame
->document(), "", channels
);
563 // We must pass in the target_origin to do the security check on this side,
564 // since it may have changed since the original postMessage call was made.
565 blink::WebSecurityOrigin target_origin
;
566 if (!serialized_event
->target_origin
.is_null()) {
567 target_origin
= blink::WebSecurityOrigin::createFromString(
568 serialized_event
->target_origin
.To
<blink::WebString
>());
570 target_web_frame
->dispatchMessageEventWithOriginCheck(target_origin
,
574 void HTMLFrame::OnWillNavigate(uint32_t target_frame_id
) {
575 HTMLFrame
* target
= frame_tree_manager_
->root_
->FindFrame(target_frame_id
);
576 if (target
&& target
->IsLocal() &&
577 target
!= frame_tree_manager_
->local_root_
) {
578 target
->SwapToRemote();
582 blink::WebMediaPlayer
* HTMLFrame::createMediaPlayer(
583 blink::WebLocalFrame
* frame
,
584 const blink::WebURL
& url
,
585 blink::WebMediaPlayerClient
* client
,
586 blink::WebMediaPlayerEncryptedMediaClient
* encrypted_client
,
587 blink::WebContentDecryptionModule
* initial_cdm
) {
588 return global_state()->media_factory()->CreateMediaPlayer(
589 frame
, url
, client
, encrypted_client
, initial_cdm
,
590 GetLocalRootApp()->shell());
593 blink::WebFrame
* HTMLFrame::createChildFrame(
594 blink::WebLocalFrame
* parent
,
595 blink::WebTreeScopeType scope
,
596 const blink::WebString
& frame_name
,
597 blink::WebSandboxFlags sandbox_flags
) {
598 DCHECK(IsLocal()); // Can't create children of remote frames.
599 DCHECK_EQ(parent
, web_frame_
);
600 DCHECK(view_
); // If we're local we have to have a view.
601 // Create the view that will house the frame now. We embed once we know the
602 // url (see decidePolicyForNavigation()).
603 mojo::View
* child_view
= view_
->connection()->CreateView();
604 ReplicatedFrameState child_state
;
605 child_state
.name
= frame_name
;
606 child_state
.tree_scope
= scope
;
607 child_state
.sandbox_flags
= sandbox_flags
;
608 mojo::Map
<mojo::String
, mojo::Array
<uint8_t>> client_properties
;
609 client_properties
.mark_non_null();
610 ClientPropertiesFromReplicatedFrameState(child_state
, &client_properties
);
612 child_view
->SetVisible(true);
613 view_
->AddChild(child_view
);
615 GetLocalRoot()->server_
->OnCreatedFrame(id_
, child_view
->id(),
616 client_properties
.Pass());
618 HTMLFrame::CreateParams
params(frame_tree_manager_
, this, child_view
->id(),
619 child_view
, client_properties
, nullptr);
620 params
.allow_local_shared_frame
= true;
621 HTMLFrame
* child_frame
=
622 GetLocalRoot()->delegate_
->GetHTMLFactory()->CreateHTMLFrame(¶ms
);
623 child_frame
->owned_view_
.reset(new mojo::ScopedViewPtr(child_view
));
624 return child_frame
->web_frame_
;
627 void HTMLFrame::frameDetached(blink::WebFrame
* web_frame
,
628 blink::WebFrameClient::DetachType type
) {
629 if (type
== blink::WebFrameClient::DetachType::Swap
) {
634 DCHECK(type
== blink::WebFrameClient::DetachType::Remove
);
635 FrameDetachedImpl(web_frame
);
638 blink::WebCookieJar
* HTMLFrame::cookieJar(blink::WebLocalFrame
* frame
) {
639 // TODO(darin): Blink does not fallback to the Platform provided WebCookieJar.
640 // Either it should, as it once did, or we should find another solution here.
641 return blink::Platform::current()->cookieJar();
644 blink::WebNavigationPolicy
HTMLFrame::decidePolicyForNavigation(
645 const NavigationPolicyInfo
& info
) {
646 // If we have extraData() it means we already have the url response
647 // (presumably because we are being called via Navigate()). In that case we
648 // can go ahead and navigate locally.
649 if (info
.urlRequest
.extraData()) {
650 DCHECK_EQ(blink::WebNavigationPolicyCurrentTab
, info
.defaultPolicy
);
651 return blink::WebNavigationPolicyCurrentTab
;
654 // Ask the FrameTreeServer to handle the navigation. By returning
655 // WebNavigationPolicyIgnore the load is suppressed.
656 mojo::URLRequestPtr url_request
= mojo::URLRequest::From(info
.urlRequest
);
657 GetLocalRoot()->server_
->RequestNavigate(
658 WebNavigationPolicyToNavigationTarget(info
.defaultPolicy
), id_
,
660 return blink::WebNavigationPolicyIgnore
;
663 void HTMLFrame::didAddMessageToConsole(const blink::WebConsoleMessage
& message
,
664 const blink::WebString
& source_name
,
665 unsigned source_line
,
666 const blink::WebString
& stack_trace
) {
667 VLOG(1) << "[" << source_name
.utf8() << "(" << source_line
<< ")] "
668 << message
.text
.utf8();
671 void HTMLFrame::didHandleOnloadEvents(blink::WebLocalFrame
* frame
) {
672 static bool recorded
= false;
673 if (!recorded
&& startup_performance_data_collector_
) {
674 startup_performance_data_collector_
->SetFirstWebContentsMainFrameLoadTime(
675 base::Time::Now().ToInternalValue());
680 void HTMLFrame::didFinishLoad(blink::WebLocalFrame
* frame
) {
681 if (GetLocalRoot() == this)
682 delegate_
->OnFrameDidFinishLoad();
685 void HTMLFrame::didNavigateWithinPage(blink::WebLocalFrame
* frame
,
686 const blink::WebHistoryItem
& history_item
,
687 blink::WebHistoryCommitType commit_type
) {
688 GetLocalRoot()->server_
->DidNavigateLocally(id_
,
689 history_item
.urlString().utf8());
692 void HTMLFrame::didFirstVisuallyNonEmptyLayout(blink::WebLocalFrame
* frame
) {
693 static bool recorded
= false;
694 if (!recorded
&& startup_performance_data_collector_
) {
695 startup_performance_data_collector_
->SetFirstVisuallyNonEmptyLayoutTime(
696 base::Time::Now().ToInternalValue());
701 blink::WebGeolocationClient
* HTMLFrame::geolocationClient() {
702 if (!geolocation_client_impl_
)
703 geolocation_client_impl_
.reset(new GeolocationClientImpl
);
704 return geolocation_client_impl_
.get();
707 blink::WebEncryptedMediaClient
* HTMLFrame::encryptedMediaClient() {
708 return global_state()->media_factory()->GetEncryptedMediaClient();
711 void HTMLFrame::didStartLoading(bool to_different_document
) {
712 GetLocalRoot()->server_
->LoadingStarted(id_
);
715 void HTMLFrame::didStopLoading() {
716 GetLocalRoot()->server_
->LoadingStopped(id_
);
719 void HTMLFrame::didChangeLoadProgress(double load_progress
) {
720 GetLocalRoot()->server_
->ProgressChanged(id_
, load_progress
);
723 void HTMLFrame::didChangeName(blink::WebLocalFrame
* frame
,
724 const blink::WebString
& name
) {
726 GetLocalRoot()->server_
->SetClientProperty(id_
, kPropertyFrameName
,
727 FrameNameToClientProperty(name
));
730 void HTMLFrame::didCommitProvisionalLoad(
731 blink::WebLocalFrame
* frame
,
732 const blink::WebHistoryItem
& item
,
733 blink::WebHistoryCommitType commit_type
) {
734 state_
.origin
= FrameOrigin(frame
);
735 GetLocalRoot()->server_
->SetClientProperty(
736 id_
, kPropertyFrameOrigin
, FrameOriginToClientProperty(frame
));
739 void HTMLFrame::didReceiveTitle(blink::WebLocalFrame
* frame
,
740 const blink::WebString
& title
,
741 blink::WebTextDirection direction
) {
742 // TODO(beng): handle |direction|.
743 mojo::String formatted
;
744 if (!title
.isNull()) {
746 mojo::String::From(base::string16(title
).substr(0, kMaxTitleChars
));
748 GetLocalRoot()->server_
->TitleChanged(id_
, formatted
);
751 void HTMLFrame::frameDetached(blink::WebRemoteFrameClient::DetachType type
) {
752 if (type
== blink::WebRemoteFrameClient::DetachType::Swap
) {
757 DCHECK(type
== blink::WebRemoteFrameClient::DetachType::Remove
);
758 FrameDetachedImpl(web_frame_
);
761 void HTMLFrame::postMessageEvent(blink::WebLocalFrame
* source_web_frame
,
762 blink::WebRemoteFrame
* target_web_frame
,
763 blink::WebSecurityOrigin target_origin
,
764 blink::WebDOMMessageEvent web_event
) {
765 NOTIMPLEMENTED(); // message_ports aren't implemented yet.
767 HTMLFrame
* source_frame
=
768 frame_tree_manager_
->root_
->FindFrameWithWebFrame(source_web_frame
);
769 DCHECK(source_frame
);
770 HTMLFrame
* target_frame
=
771 frame_tree_manager_
->root_
->FindFrameWithWebFrame(target_web_frame
);
772 DCHECK(target_frame
);
774 HTMLMessageEventPtr
event(HTMLMessageEvent::New());
775 event
->data
= mojo::Array
<uint8_t>::From(web_event
.data().toString());
776 event
->source_origin
= mojo::String::From(web_event
.origin());
777 if (!target_origin
.isNull())
778 event
->target_origin
= mojo::String::From(target_origin
.toString());
780 GetFrameTreeServer()->PostMessageEventToFrame(
781 source_frame
->id_
, target_frame
->id_
, event
.Pass());
784 void HTMLFrame::initializeChildFrame(const blink::WebRect
& frame_rect
,
785 float scale_factor
) {
786 // NOTE: |scale_factor| is always 1.
787 const gfx::Rect
rect_in_dip(frame_rect
.x
, frame_rect
.y
, frame_rect
.width
,
789 const gfx::Rect
rect_in_pixels(gfx::ConvertRectToPixel(
790 global_state()->device_pixel_ratio(), rect_in_dip
));
791 const mojo::RectPtr
mojo_rect_in_pixels(mojo::Rect::From(rect_in_pixels
));
792 view_
->SetBounds(*mojo_rect_in_pixels
);
795 void HTMLFrame::navigate(const blink::WebURLRequest
& request
,
796 bool should_replace_current_entry
) {
797 // TODO: support |should_replace_current_entry|.
798 NOTIMPLEMENTED(); // for |should_replace_current_entry
799 mojo::URLRequestPtr url_request
= mojo::URLRequest::From(request
);
800 GetFrameTreeServer()->RequestNavigate(
801 web_view::NAVIGATION_TARGET_TYPE_EXISTING_FRAME
, id_
, url_request
.Pass());
804 void HTMLFrame::reload(bool ignore_cache
, bool is_client_redirect
) {
808 void HTMLFrame::forwardInputEvent(const blink::WebInputEvent
* event
) {