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_frame_delegate.h"
24 #include "components/html_viewer/html_frame_properties.h"
25 #include "components/html_viewer/html_frame_tree_manager.h"
26 #include "components/html_viewer/media_factory.h"
27 #include "components/html_viewer/stats_collection_controller.h"
28 #include "components/html_viewer/touch_handler.h"
29 #include "components/html_viewer/web_layer_impl.h"
30 #include "components/html_viewer/web_layer_tree_view_impl.h"
31 #include "components/html_viewer/web_storage_namespace_impl.h"
32 #include "components/html_viewer/web_url_loader_impl.h"
33 #include "components/view_manager/ids.h"
34 #include "components/view_manager/public/cpp/scoped_view_ptr.h"
35 #include "components/view_manager/public/cpp/view.h"
36 #include "components/view_manager/public/cpp/view_manager.h"
37 #include "components/view_manager/public/interfaces/surfaces.mojom.h"
38 #include "mojo/application/public/cpp/application_impl.h"
39 #include "mojo/application/public/cpp/connect.h"
40 #include "mojo/application/public/interfaces/shell.mojom.h"
41 #include "mojo/common/common_type_converters.h"
42 #include "mojo/converters/geometry/geometry_type_converters.h"
43 #include "skia/ext/refptr.h"
44 #include "third_party/WebKit/public/platform/Platform.h"
45 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
46 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
47 #include "third_party/WebKit/public/platform/WebSize.h"
48 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
49 #include "third_party/WebKit/public/web/WebDocument.h"
50 #include "third_party/WebKit/public/web/WebElement.h"
51 #include "third_party/WebKit/public/web/WebFrameWidget.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/WebSettings.h"
60 #include "third_party/WebKit/public/web/WebView.h"
61 #include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h"
62 #include "third_party/skia/include/core/SkCanvas.h"
63 #include "third_party/skia/include/core/SkColor.h"
64 #include "third_party/skia/include/core/SkDevice.h"
65 #include "ui/gfx/geometry/dip_util.h"
66 #include "ui/gfx/geometry/size.h"
67 #include "url/origin.h"
69 using mandoline::HTMLMessageEvent
;
70 using mandoline::HTMLMessageEventPtr
;
71 using mojo::AxProvider
;
73 using mojo::ServiceProviderPtr
;
74 using mojo::URLResponsePtr
;
77 namespace html_viewer
{
80 mandoline::NavigationTargetType
WebNavigationPolicyToNavigationTarget(
81 blink::WebNavigationPolicy policy
) {
83 case blink::WebNavigationPolicyCurrentTab
:
84 return mandoline::NAVIGATION_TARGET_TYPE_EXISTING_FRAME
;
85 case blink::WebNavigationPolicyNewBackgroundTab
:
86 case blink::WebNavigationPolicyNewForegroundTab
:
87 case blink::WebNavigationPolicyNewWindow
:
88 case blink::WebNavigationPolicyNewPopup
:
89 return mandoline::NAVIGATION_TARGET_TYPE_NEW_FRAME
;
91 return mandoline::NAVIGATION_TARGET_TYPE_NO_PREFERENCE
;
95 void ConfigureSettings(blink::WebSettings
* settings
) {
96 settings
->setCookieEnabled(true);
97 settings
->setDefaultFixedFontSize(13);
98 settings
->setDefaultFontSize(16);
99 settings
->setLoadsImagesAutomatically(true);
100 settings
->setJavaScriptEnabled(true);
103 HTMLFrame
* GetPreviousSibling(HTMLFrame
* frame
) {
104 DCHECK(frame
->parent());
105 auto iter
= std::find(frame
->parent()->children().begin(),
106 frame
->parent()->children().end(), frame
);
107 return (iter
== frame
->parent()->children().begin()) ? nullptr : *(--iter
);
112 HTMLFrame::HTMLFrame(CreateParams
* params
)
113 : frame_tree_manager_(params
->manager
),
114 parent_(params
->parent
),
118 web_widget_(nullptr),
119 delegate_(params
->delegate
),
120 weak_factory_(this) {
122 parent_
->children_
.push_back(this);
124 if (params
->view
&& params
->view
->id() == id_
)
125 SetView(params
->view
);
127 SetReplicatedFrameStateFromClientProperties(params
->properties
, &state_
);
130 CreateRootWebWidget();
131 // This is the root of the tree (aka the main frame).
132 // Expected order for creating webframes is:
133 // . Create local webframe (first webframe must always be local).
134 // . Set as main frame on WebView.
135 // . Swap to remote (if not local).
136 blink::WebLocalFrame
* local_web_frame
=
137 blink::WebLocalFrame::create(state_
.tree_scope
, this);
138 // We need to set the main frame before creating children so that state is
139 // properly set up in blink.
140 web_view()->setMainFrame(local_web_frame
);
141 const gfx::Size
size_in_pixels(params
->view
->bounds().width
,
142 params
->view
->bounds().height
);
143 const gfx::Size size_in_dips
= gfx::ConvertSizeToDIP(
144 params
->view
->viewport_metrics().device_pixel_ratio
, size_in_pixels
);
145 web_widget_
->resize(size_in_dips
);
146 web_frame_
= local_web_frame
;
147 web_view()->setDeviceScaleFactor(global_state()->device_pixel_ratio());
148 if (id_
!= params
->view
->id()) {
149 blink::WebRemoteFrame
* remote_web_frame
=
150 blink::WebRemoteFrame::create(state_
.tree_scope
, this);
151 local_web_frame
->swap(remote_web_frame
);
152 web_frame_
= remote_web_frame
;
154 // Setup a DevTools agent if this is the local main frame and the browser
155 // side has set relevant client properties.
156 mojo::Array
<uint8_t> devtools_id
=
157 GetValueFromClientProperties("devtools-id", params
->properties
);
158 if (!devtools_id
.is_null()) {
159 mojo::Array
<uint8_t> devtools_state
=
160 GetValueFromClientProperties("devtools-state", params
->properties
);
161 std::string devtools_state_str
= devtools_state
.To
<std::string
>();
162 devtools_agent_
.reset(new DevToolsAgentImpl(
163 web_frame_
->toWebLocalFrame(), devtools_id
.To
<std::string
>(),
164 devtools_state
.is_null() ? nullptr : &devtools_state_str
));
167 // Collect startup perf data for local main frames in test environments.
168 // Child frames aren't tracked, and tracking remote frames is redundant.
169 startup_performance_data_collector_
=
170 StatsCollectionController::Install(web_frame_
, GetLocalRootApp());
172 } else if (!params
->allow_local_shared_frame
&& params
->view
&&
173 id_
== params
->view
->id()) {
174 // Frame represents the local frame, and it isn't the root of the tree.
175 HTMLFrame
* previous_sibling
= GetPreviousSibling(this);
176 blink::WebFrame
* previous_web_frame
=
177 previous_sibling
? previous_sibling
->web_frame() : nullptr;
178 DCHECK(!parent_
->IsLocal());
179 web_frame_
= parent_
->web_frame()->toWebRemoteFrame()->createLocalChild(
180 state_
.tree_scope
, state_
.name
, state_
.sandbox_flags
, this,
182 CreateLocalRootWebWidget(web_frame_
->toWebLocalFrame());
183 } else if (!parent_
->IsLocal()) {
184 web_frame_
= parent_
->web_frame()->toWebRemoteFrame()->createRemoteChild(
185 state_
.tree_scope
, state_
.name
, state_
.sandbox_flags
, this);
187 // TODO(sky): this DCHECK, and |allow_local_shared_frame| should be
188 // moved to HTMLFrameTreeManager. It makes more sense there.
189 // This should never happen (if we create a local child we don't call
190 // Init(), and the frame server should not being creating child frames of
192 DCHECK(params
->allow_local_shared_frame
);
194 blink::WebLocalFrame
* child_web_frame
=
195 blink::WebLocalFrame::create(state_
.tree_scope
, this);
196 web_frame_
= child_web_frame
;
197 parent_
->web_frame_
->appendChild(child_web_frame
);
201 blink::WebRemoteFrame
* remote_web_frame
= web_frame_
->toWebRemoteFrame();
202 if (remote_web_frame
) {
203 remote_web_frame
->setReplicatedOrigin(state_
.origin
);
204 remote_web_frame
->setReplicatedName(state_
.name
);
209 void HTMLFrame::Close() {
211 // Closing the root widget (WebView) implicitly detaches. For children
212 // (which have a WebFrameWidget) a detach() is required. Use a temporary
213 // as if 'this' is the root the call to web_widget_->close() deletes
215 const bool is_child
= parent_
!= nullptr;
216 web_widget_
->close();
218 web_frame_
->detach();
220 web_frame_
->detach();
224 const HTMLFrame
* HTMLFrame::FindFrame(uint32_t id
) const {
228 for (const HTMLFrame
* child
: children_
) {
229 const HTMLFrame
* match
= child
->FindFrame(id
);
236 blink::WebView
* HTMLFrame::web_view() {
237 return web_widget_
&& web_widget_
->isWebView()
238 ? static_cast<blink::WebView
*>(web_widget_
)
242 bool HTMLFrame::HasLocalDescendant() const {
246 for (HTMLFrame
* child
: children_
) {
247 if (child
->HasLocalDescendant())
253 HTMLFrame::~HTMLFrame() {
254 DCHECK(children_
.empty());
258 std::find(parent_
->children_
.begin(), parent_
->children_
.end(), this);
259 parent_
->children_
.erase(iter
);
263 frame_tree_manager_
->OnFrameDestroyed(this);
266 view_
->RemoveObserver(this);
267 mojo::ScopedViewPtr::DeleteViewOrViewManager(view_
);
271 void HTMLFrame::Bind(mandoline::FrameTreeServerPtr frame_tree_server
,
272 mojo::InterfaceRequest
<mandoline::FrameTreeClient
>
273 frame_tree_client_request
) {
275 // TODO(sky): error handling.
276 server_
= frame_tree_server
.Pass();
277 frame_tree_client_binding_
.reset(
278 new mojo::Binding
<mandoline::FrameTreeClient
>(
279 this, frame_tree_client_request
.Pass()));
282 void HTMLFrame::SetValueFromClientProperty(const std::string
& name
,
283 mojo::Array
<uint8_t> new_data
) {
287 // Only the name and origin dynamically change.
288 if (name
== kPropertyFrameOrigin
) {
289 state_
.origin
= FrameOriginFromClientProperty(new_data
);
290 web_frame_
->toWebRemoteFrame()->setReplicatedOrigin(state_
.origin
);
291 } else if (name
== kPropertyFrameName
) {
292 state_
.name
= FrameNameFromClientProperty(new_data
);
293 web_frame_
->toWebRemoteFrame()->setReplicatedName(state_
.name
);
297 bool HTMLFrame::IsLocal() const {
298 return web_frame_
->isWebLocalFrame();
301 HTMLFrame
* HTMLFrame::GetLocalRoot() {
302 HTMLFrame
* frame
= this;
303 while (frame
&& !frame
->delegate_
)
304 frame
= frame
->parent_
;
308 mojo::ApplicationImpl
* HTMLFrame::GetLocalRootApp() {
309 return GetLocalRoot()->delegate_
->GetApp();
312 mandoline::FrameTreeServer
* HTMLFrame::GetFrameTreeServer() {
313 // Prefer the local root.
314 HTMLFrame
* local_root
= GetLocalRoot();
316 return local_root
->server_
.get();
318 // No local root. This means we're a remote frame with no local frame
319 // ancestors. Use the local frame from the FrameTreeServer.
320 return frame_tree_manager_
->local_root_
->server_
.get();
323 void HTMLFrame::SetView(mojo::View
* view
) {
325 view_
->RemoveObserver(this);
328 view_
->AddObserver(this);
331 void HTMLFrame::CreateRootWebWidget() {
332 DCHECK(!web_widget_
);
333 blink::WebViewClient
* web_view_client
=
334 (view_
&& view_
->id() == id_
) ? this : nullptr;
335 web_widget_
= blink::WebView::create(web_view_client
);
337 InitializeWebWidget();
339 ConfigureSettings(web_view()->settings());
342 void HTMLFrame::CreateLocalRootWebWidget(blink::WebLocalFrame
* local_frame
) {
343 DCHECK(!web_widget_
);
345 web_widget_
= blink::WebFrameWidget::create(this, local_frame
);
347 InitializeWebWidget();
350 void HTMLFrame::InitializeWebWidget() {
351 // Creating the widget calls initializeLayerTreeView() to create the
352 // |web_layer_tree_view_impl_|. As we haven't yet assigned the |web_widget_|
353 // we have to set it here.
354 if (web_layer_tree_view_impl_
) {
355 web_layer_tree_view_impl_
->set_widget(web_widget_
);
356 web_layer_tree_view_impl_
->set_view(view_
);
357 UpdateWebViewSizeFromViewSize();
361 void HTMLFrame::UpdateFocus() {
362 if (!web_widget_
|| !view_
)
364 const bool is_focused
= view_
&& view_
->HasFocus();
365 web_widget_
->setFocus(is_focused
);
366 if (web_widget_
->isWebView())
367 static_cast<blink::WebView
*>(web_widget_
)->setIsActive(is_focused
);
370 void HTMLFrame::UpdateWebViewSizeFromViewSize() {
371 if (!web_widget_
|| !view_
)
374 const gfx::Size
size_in_pixels(view_
->bounds().width
, view_
->bounds().height
);
375 const gfx::Size size_in_dips
= gfx::ConvertSizeToDIP(
376 view_
->viewport_metrics().device_pixel_ratio
, size_in_pixels
);
378 blink::WebSize(size_in_dips
.width(), size_in_dips
.height()));
379 web_layer_tree_view_impl_
->setViewportSize(size_in_pixels
);
382 void HTMLFrame::SwapToRemote() {
385 HTMLFrameDelegate
* delegate
= delegate_
;
388 blink::WebRemoteFrame
* remote_frame
=
389 blink::WebRemoteFrame::create(state_
.tree_scope
, this);
390 remote_frame
->initializeFromFrame(web_frame_
->toWebLocalFrame());
391 // swap() ends up calling us back and we then close the frame, which deletes
393 web_frame_
->swap(remote_frame
);
394 // TODO(sky): this isn't quite right, but WebLayerImpl is temporary.
397 new WebLayerImpl(owned_view_
->view(),
398 global_state()->device_pixel_ratio()));
400 remote_frame
->setRemoteWebLayer(web_layer_
.get());
401 remote_frame
->setReplicatedName(state_
.name
);
402 remote_frame
->setReplicatedOrigin(state_
.origin
);
403 remote_frame
->setReplicatedSandboxFlags(state_
.sandbox_flags
);
404 web_frame_
= remote_frame
;
407 delegate
->OnFrameSwappedToRemote();
410 void HTMLFrame::SwapToLocal(
411 HTMLFrameDelegate
* delegate
,
413 const mojo::Map
<mojo::String
, mojo::Array
<uint8_t>>& properties
) {
415 // It doesn't make sense for the root to swap to local.
417 delegate_
= delegate
;
419 SetReplicatedFrameStateFromClientProperties(properties
, &state_
);
420 blink::WebLocalFrame
* local_web_frame
=
421 blink::WebLocalFrame::create(state_
.tree_scope
, this);
422 local_web_frame
->initializeToReplaceRemoteFrame(
423 web_frame_
->toWebRemoteFrame(), state_
.name
, state_
.sandbox_flags
);
424 // The swap() ends up calling to frameDetached() and deleting the old.
425 web_frame_
->swap(local_web_frame
);
426 web_frame_
= local_web_frame
;
431 HTMLFrame
* HTMLFrame::FindFrameWithWebFrame(blink::WebFrame
* web_frame
) {
432 if (web_frame_
== web_frame
)
434 for (HTMLFrame
* child_frame
: children_
) {
435 HTMLFrame
* result
= child_frame
->FindFrameWithWebFrame(web_frame
);
442 void HTMLFrame::FrameDetachedImpl(blink::WebFrame
* web_frame
) {
443 DCHECK_EQ(web_frame_
, web_frame
);
445 while (!children_
.empty()) {
446 HTMLFrame
* child
= children_
.front();
448 DCHECK(children_
.empty() || children_
.front() != child
);
451 if (web_frame
->parent())
452 web_frame
->parent()->removeChild(web_frame
);
457 void HTMLFrame::OnViewBoundsChanged(View
* view
,
458 const Rect
& old_bounds
,
459 const Rect
& new_bounds
) {
460 DCHECK_EQ(view
, view_
);
461 UpdateWebViewSizeFromViewSize();
464 void HTMLFrame::OnViewDestroyed(View
* view
) {
465 DCHECK_EQ(view
, view_
);
466 view_
->RemoveObserver(this);
471 void HTMLFrame::OnViewInputEvent(View
* view
, const mojo::EventPtr
& event
) {
472 if (event
->pointer_data
) {
473 // Blink expects coordintes to be in DIPs.
474 event
->pointer_data
->x
/= global_state()->device_pixel_ratio();
475 event
->pointer_data
->y
/= global_state()->device_pixel_ratio();
476 event
->pointer_data
->screen_x
/= global_state()->device_pixel_ratio();
477 event
->pointer_data
->screen_y
/= global_state()->device_pixel_ratio();
480 if (!touch_handler_
&& web_widget_
)
481 touch_handler_
.reset(new TouchHandler(web_widget_
));
483 if ((event
->action
== mojo::EVENT_TYPE_POINTER_DOWN
||
484 event
->action
== mojo::EVENT_TYPE_POINTER_UP
||
485 event
->action
== mojo::EVENT_TYPE_POINTER_CANCEL
||
486 event
->action
== mojo::EVENT_TYPE_POINTER_MOVE
) &&
487 event
->pointer_data
->kind
== mojo::POINTER_KIND_TOUCH
) {
488 touch_handler_
->OnTouchEvent(*event
);
495 scoped_ptr
<blink::WebInputEvent
> web_event
=
496 event
.To
<scoped_ptr
<blink::WebInputEvent
>>();
498 web_widget_
->handleInputEvent(*web_event
);
501 void HTMLFrame::OnViewFocusChanged(mojo::View
* gained_focus
,
502 mojo::View
* lost_focus
) {
506 void HTMLFrame::OnConnect(mandoline::FrameTreeServerPtr server
,
508 mojo::Array
<mandoline::FrameDataPtr
> frame_data
) {
509 // OnConnect() is only sent once, and has been received (by
510 // DocumentResourceWaiter) by the time we get here.
514 void HTMLFrame::OnFrameAdded(uint32_t change_id
,
515 mandoline::FrameDataPtr frame_data
) {
516 frame_tree_manager_
->ProcessOnFrameAdded(this, change_id
, frame_data
.Pass());
519 void HTMLFrame::OnFrameRemoved(uint32_t change_id
, uint32_t frame_id
) {
520 frame_tree_manager_
->ProcessOnFrameRemoved(this, change_id
, frame_id
);
523 void HTMLFrame::OnFrameClientPropertyChanged(uint32_t frame_id
,
524 const mojo::String
& name
,
525 mojo::Array
<uint8_t> new_value
) {
526 frame_tree_manager_
->ProcessOnFrameClientPropertyChanged(this, frame_id
, name
,
530 void HTMLFrame::OnPostMessageEvent(uint32_t source_frame_id
,
531 uint32_t target_frame_id
,
532 HTMLMessageEventPtr serialized_event
) {
533 NOTIMPLEMENTED(); // For message ports.
535 HTMLFrame
* target
= frame_tree_manager_
->root_
->FindFrame(target_frame_id
);
536 HTMLFrame
* source
= frame_tree_manager_
->root_
->FindFrame(source_frame_id
);
537 if (!target
|| !source
) {
538 DVLOG(1) << "Invalid source or target for PostMessage";
542 if (!target
->IsLocal()) {
543 DVLOG(1) << "Target for PostMessage is not lot local";
547 blink::WebLocalFrame
* target_web_frame
=
548 target
->web_frame_
->toWebLocalFrame();
550 blink::WebSerializedScriptValue serialized_script_value
;
551 serialized_script_value
= blink::WebSerializedScriptValue::fromString(
552 serialized_event
->data
.To
<blink::WebString
>());
554 blink::WebMessagePortChannelArray channels
;
556 // Create an event with the message. The next-to-last parameter to
557 // initMessageEvent is the last event ID, which is not used with postMessage.
558 blink::WebDOMEvent event
=
559 target_web_frame
->document().createEvent("MessageEvent");
560 blink::WebDOMMessageEvent msg_event
= event
.to
<blink::WebDOMMessageEvent
>();
561 msg_event
.initMessageEvent(
563 // |canBubble| and |cancellable| are always false
564 false, false, serialized_script_value
,
565 serialized_event
->source_origin
.To
<blink::WebString
>(),
566 source
->web_frame_
, target_web_frame
->document(), "", channels
);
568 // We must pass in the target_origin to do the security check on this side,
569 // since it may have changed since the original postMessage call was made.
570 blink::WebSecurityOrigin target_origin
;
571 if (!serialized_event
->target_origin
.is_null()) {
572 target_origin
= blink::WebSecurityOrigin::createFromString(
573 serialized_event
->target_origin
.To
<blink::WebString
>());
575 target_web_frame
->dispatchMessageEventWithOriginCheck(target_origin
,
579 void HTMLFrame::OnWillNavigate(uint32_t target_frame_id
,
580 const OnWillNavigateCallback
& callback
) {
581 // Assume this process won't service the connection and swap to remote.
582 // It's entirely possible this process will service the connection and we
583 // don't need to swap, but the naive approach is much simpler.
584 HTMLFrame
* target
= frame_tree_manager_
->root_
->FindFrame(target_frame_id
);
585 if (target
&& target
->IsLocal() &&
586 target
!= frame_tree_manager_
->local_root_
) {
587 target
->SwapToRemote();
592 blink::WebStorageNamespace
* HTMLFrame::createSessionStorageNamespace() {
593 return new WebStorageNamespaceImpl();
596 void HTMLFrame::didCancelCompositionOnSelectionChange() {
597 // TODO(penghuang): Update text input state.
600 void HTMLFrame::didChangeContents() {
601 // TODO(penghuang): Update text input state.
604 void HTMLFrame::initializeLayerTreeView() {
605 mojo::URLRequestPtr
request(mojo::URLRequest::New());
606 request
->url
= mojo::String::From("mojo:view_manager");
607 mojo::SurfacePtr surface
;
608 GetLocalRootApp()->ConnectToService(request
.Pass(), &surface
);
610 mojo::URLRequestPtr
request2(mojo::URLRequest::New());
611 request2
->url
= mojo::String::From("mojo:view_manager");
612 mojo::GpuPtr gpu_service
;
613 GetLocalRootApp()->ConnectToService(request2
.Pass(), &gpu_service
);
614 web_layer_tree_view_impl_
.reset(new WebLayerTreeViewImpl(
615 global_state()->compositor_thread(),
616 global_state()->gpu_memory_buffer_manager(),
617 global_state()->raster_thread_helper()->task_graph_runner(),
618 surface
.Pass(), gpu_service
.Pass()));
621 blink::WebLayerTreeView
* HTMLFrame::layerTreeView() {
622 return web_layer_tree_view_impl_
.get();
625 void HTMLFrame::resetInputMethod() {
626 // When this method gets called, WebWidgetClient implementation should
627 // reset the input method by cancelling any ongoing composition.
628 // TODO(penghuang): Reset IME.
631 void HTMLFrame::didHandleGestureEvent(const blink::WebGestureEvent
& event
,
632 bool eventCancelled
) {
633 // Called when a gesture event is handled.
637 if (event
.type
== blink::WebInputEvent::GestureTap
) {
638 const bool show_ime
= true;
639 UpdateTextInputState(show_ime
);
640 } else if (event
.type
== blink::WebInputEvent::GestureLongPress
) {
641 // Only show IME if the textfield contains text.
642 const bool show_ime
=
643 !web_view()->textInputInfo().value
.isEmpty();
644 UpdateTextInputState(show_ime
);
648 void HTMLFrame::didUpdateTextOfFocusedElementByNonUserInput() {
649 // Called when value of focused textfield gets dirty, e.g. value is
650 // modified by script, not by user input.
651 const bool show_ime
= false;
652 UpdateTextInputState(show_ime
);
655 void HTMLFrame::showImeIfNeeded() {
656 // Request the browser to show the IME for current input type.
657 const bool show_ime
= true;
658 UpdateTextInputState(show_ime
);
661 blink::WebMediaPlayer
* HTMLFrame::createMediaPlayer(
662 blink::WebLocalFrame
* frame
,
663 const blink::WebURL
& url
,
664 blink::WebMediaPlayerClient
* client
,
665 blink::WebMediaPlayerEncryptedMediaClient
* encrypted_client
,
666 blink::WebContentDecryptionModule
* initial_cdm
) {
667 return global_state()->media_factory()->CreateMediaPlayer(
668 frame
, url
, client
, encrypted_client
, initial_cdm
,
669 GetLocalRootApp()->shell());
672 blink::WebFrame
* HTMLFrame::createChildFrame(
673 blink::WebLocalFrame
* parent
,
674 blink::WebTreeScopeType scope
,
675 const blink::WebString
& frame_name
,
676 blink::WebSandboxFlags sandbox_flags
) {
677 DCHECK(IsLocal()); // Can't create children of remote frames.
678 DCHECK_EQ(parent
, web_frame_
);
679 DCHECK(view_
); // If we're local we have to have a view.
680 // Create the view that will house the frame now. We embed once we know the
681 // url (see decidePolicyForNavigation()).
682 mojo::View
* child_view
= view_
->view_manager()->CreateView();
683 ReplicatedFrameState child_state
;
684 child_state
.name
= frame_name
;
685 child_state
.tree_scope
= scope
;
686 child_state
.sandbox_flags
= sandbox_flags
;
687 mojo::Map
<mojo::String
, mojo::Array
<uint8_t>> client_properties
;
688 client_properties
.mark_non_null();
689 ClientPropertiesFromReplicatedFrameState(child_state
, &client_properties
);
691 child_view
->SetVisible(true);
692 view_
->AddChild(child_view
);
694 GetLocalRoot()->server_
->OnCreatedFrame(id_
, child_view
->id(),
695 client_properties
.Pass());
697 HTMLFrame::CreateParams
params(frame_tree_manager_
, this, child_view
->id(),
698 child_view
, client_properties
, nullptr);
699 params
.allow_local_shared_frame
= true;
700 HTMLFrame
* child_frame
= GetLocalRoot()->delegate_
->CreateHTMLFrame(¶ms
);
701 child_frame
->owned_view_
.reset(new mojo::ScopedViewPtr(child_view
));
702 return child_frame
->web_frame_
;
705 void HTMLFrame::frameDetached(blink::WebFrame
* web_frame
,
706 blink::WebFrameClient::DetachType type
) {
707 if (type
== blink::WebFrameClient::DetachType::Swap
) {
712 DCHECK(type
== blink::WebFrameClient::DetachType::Remove
);
713 FrameDetachedImpl(web_frame
);
716 blink::WebCookieJar
* HTMLFrame::cookieJar(blink::WebLocalFrame
* frame
) {
717 // TODO(darin): Blink does not fallback to the Platform provided WebCookieJar.
718 // Either it should, as it once did, or we should find another solution here.
719 return blink::Platform::current()->cookieJar();
722 blink::WebNavigationPolicy
HTMLFrame::decidePolicyForNavigation(
723 const NavigationPolicyInfo
& info
) {
724 // If we have extraData() it means we already have the url response
725 // (presumably because we are being called via Navigate()). In that case we
726 // can go ahead and navigate locally.
727 if (info
.urlRequest
.extraData()) {
728 DCHECK_EQ(blink::WebNavigationPolicyCurrentTab
, info
.defaultPolicy
);
729 return blink::WebNavigationPolicyCurrentTab
;
732 // Ask the FrameTreeServer to handle the navigation. By returning
733 // WebNavigationPolicyIgnore the load is suppressed.
734 mojo::URLRequestPtr url_request
= mojo::URLRequest::From(info
.urlRequest
);
735 GetLocalRoot()->server_
->RequestNavigate(
736 WebNavigationPolicyToNavigationTarget(info
.defaultPolicy
), id_
,
738 return blink::WebNavigationPolicyIgnore
;
741 void HTMLFrame::didAddMessageToConsole(const blink::WebConsoleMessage
& message
,
742 const blink::WebString
& source_name
,
743 unsigned source_line
,
744 const blink::WebString
& stack_trace
) {
745 VLOG(1) << "[" << source_name
.utf8() << "(" << source_line
<< ")] "
746 << message
.text
.utf8();
749 void HTMLFrame::didHandleOnloadEvents(blink::WebLocalFrame
* frame
) {
750 static bool recorded
= false;
751 if (!recorded
&& startup_performance_data_collector_
) {
752 startup_performance_data_collector_
->SetFirstWebContentsMainFrameLoadTime(
753 base::Time::Now().ToInternalValue());
758 void HTMLFrame::didFinishLoad(blink::WebLocalFrame
* frame
) {
759 if (GetLocalRoot() == this)
760 delegate_
->OnFrameDidFinishLoad();
763 void HTMLFrame::didNavigateWithinPage(blink::WebLocalFrame
* frame
,
764 const blink::WebHistoryItem
& history_item
,
765 blink::WebHistoryCommitType commit_type
) {
766 GetLocalRoot()->server_
->DidNavigateLocally(id_
,
767 history_item
.urlString().utf8());
770 void HTMLFrame::didFirstVisuallyNonEmptyLayout(blink::WebLocalFrame
* frame
) {
771 static bool recorded
= false;
772 if (!recorded
&& startup_performance_data_collector_
) {
773 startup_performance_data_collector_
->SetFirstVisuallyNonEmptyLayoutTime(
774 base::Time::Now().ToInternalValue());
779 blink::WebGeolocationClient
* HTMLFrame::geolocationClient() {
780 if (!geolocation_client_impl_
)
781 geolocation_client_impl_
.reset(new GeolocationClientImpl
);
782 return geolocation_client_impl_
.get();
785 blink::WebEncryptedMediaClient
* HTMLFrame::encryptedMediaClient() {
786 return global_state()->media_factory()->GetEncryptedMediaClient();
789 void HTMLFrame::didStartLoading(bool to_different_document
) {
790 GetLocalRoot()->server_
->LoadingStarted(id_
);
793 void HTMLFrame::didStopLoading() {
794 GetLocalRoot()->server_
->LoadingStopped(id_
);
797 void HTMLFrame::didChangeLoadProgress(double load_progress
) {
798 GetLocalRoot()->server_
->ProgressChanged(id_
, load_progress
);
801 void HTMLFrame::didChangeName(blink::WebLocalFrame
* frame
,
802 const blink::WebString
& name
) {
804 GetLocalRoot()->server_
->SetClientProperty(id_
, kPropertyFrameName
,
805 FrameNameToClientProperty(name
));
808 void HTMLFrame::didCommitProvisionalLoad(
809 blink::WebLocalFrame
* frame
,
810 const blink::WebHistoryItem
& item
,
811 blink::WebHistoryCommitType commit_type
) {
812 state_
.origin
= FrameOrigin(frame
);
813 GetLocalRoot()->server_
->SetClientProperty(
814 id_
, kPropertyFrameOrigin
, FrameOriginToClientProperty(frame
));
817 void HTMLFrame::frameDetached(blink::WebRemoteFrameClient::DetachType type
) {
818 if (type
== blink::WebRemoteFrameClient::DetachType::Swap
) {
823 DCHECK(type
== blink::WebRemoteFrameClient::DetachType::Remove
);
824 FrameDetachedImpl(web_frame_
);
827 void HTMLFrame::UpdateTextInputState(bool show_ime
) {
828 blink::WebTextInputInfo new_info
= web_view()->textInputInfo();
829 // Only show IME if the focused element is editable.
830 show_ime
= show_ime
&& new_info
.type
!= blink::WebTextInputTypeNone
;
831 if (show_ime
|| text_input_info_
!= new_info
) {
832 text_input_info_
= new_info
;
833 mojo::TextInputStatePtr state
= mojo::TextInputState::New();
834 state
->type
= mojo::ConvertTo
<mojo::TextInputType
>(new_info
.type
);
835 state
->flags
= new_info
.flags
;
836 state
->text
= mojo::String::From(new_info
.value
.utf8());
837 state
->selection_start
= new_info
.selectionStart
;
838 state
->selection_end
= new_info
.selectionEnd
;
839 state
->composition_start
= new_info
.compositionStart
;
840 state
->composition_end
= new_info
.compositionEnd
;
842 view_
->SetImeVisibility(true, state
.Pass());
844 view_
->SetTextInputState(state
.Pass());
848 void HTMLFrame::postMessageEvent(blink::WebLocalFrame
* source_web_frame
,
849 blink::WebRemoteFrame
* target_web_frame
,
850 blink::WebSecurityOrigin target_origin
,
851 blink::WebDOMMessageEvent web_event
) {
852 NOTIMPLEMENTED(); // message_ports aren't implemented yet.
854 HTMLFrame
* source_frame
=
855 frame_tree_manager_
->root_
->FindFrameWithWebFrame(source_web_frame
);
856 DCHECK(source_frame
);
857 HTMLFrame
* target_frame
=
858 frame_tree_manager_
->root_
->FindFrameWithWebFrame(target_web_frame
);
859 DCHECK(target_frame
);
861 HTMLMessageEventPtr
event(HTMLMessageEvent::New());
862 event
->data
= mojo::Array
<uint8_t>::From(web_event
.data().toString());
863 event
->source_origin
= mojo::String::From(web_event
.origin());
864 if (!target_origin
.isNull())
865 event
->target_origin
= mojo::String::From(target_origin
.toString());
867 GetFrameTreeServer()->PostMessageEventToFrame(
868 source_frame
->id_
, target_frame
->id_
, event
.Pass());
871 void HTMLFrame::initializeChildFrame(const blink::WebRect
& frame_rect
,
872 float scale_factor
) {
873 // NOTE: |scale_factor| is always 1.
874 const gfx::Rect
rect_in_dip(frame_rect
.x
, frame_rect
.y
, frame_rect
.width
,
876 const gfx::Rect
rect_in_pixels(gfx::ConvertRectToPixel(
877 global_state()->device_pixel_ratio(), rect_in_dip
));
878 const mojo::RectPtr
mojo_rect_in_pixels(mojo::Rect::From(rect_in_pixels
));
879 view_
->SetBounds(*mojo_rect_in_pixels
);
882 void HTMLFrame::navigate(const blink::WebURLRequest
& request
,
883 bool should_replace_current_entry
) {
884 // TODO: support |should_replace_current_entry|.
885 NOTIMPLEMENTED(); // for |should_replace_current_entry
886 mojo::URLRequestPtr url_request
= mojo::URLRequest::From(request
);
887 GetFrameTreeServer()->RequestNavigate(
888 mandoline::NAVIGATION_TARGET_TYPE_EXISTING_FRAME
, id_
,
892 void HTMLFrame::reload(bool ignore_cache
, bool is_client_redirect
) {
896 void HTMLFrame::forwardInputEvent(const blink::WebInputEvent
* event
) {