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_url_request_type_converters.h"
19 #include "components/html_viewer/geolocation_client_impl.h"
20 #include "components/html_viewer/global_state.h"
21 #include "components/html_viewer/html_frame_delegate.h"
22 #include "components/html_viewer/html_frame_properties.h"
23 #include "components/html_viewer/html_frame_tree_manager.h"
24 #include "components/html_viewer/media_factory.h"
25 #include "components/html_viewer/touch_handler.h"
26 #include "components/html_viewer/web_layer_impl.h"
27 #include "components/html_viewer/web_layer_tree_view_impl.h"
28 #include "components/html_viewer/web_storage_namespace_impl.h"
29 #include "components/html_viewer/web_url_loader_impl.h"
30 #include "components/view_manager/ids.h"
31 #include "components/view_manager/public/cpp/view.h"
32 #include "components/view_manager/public/cpp/view_manager.h"
33 #include "components/view_manager/public/interfaces/surfaces.mojom.h"
34 #include "mandoline/services/navigation/public/interfaces/navigation.mojom.h"
35 #include "mojo/application/public/cpp/application_impl.h"
36 #include "mojo/application/public/cpp/connect.h"
37 #include "mojo/application/public/interfaces/shell.mojom.h"
38 #include "mojo/converters/geometry/geometry_type_converters.h"
39 #include "skia/ext/refptr.h"
40 #include "third_party/WebKit/public/platform/Platform.h"
41 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
42 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
43 #include "third_party/WebKit/public/platform/WebSize.h"
44 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
45 #include "third_party/WebKit/public/web/WebDocument.h"
46 #include "third_party/WebKit/public/web/WebElement.h"
47 #include "third_party/WebKit/public/web/WebFrameWidget.h"
48 #include "third_party/WebKit/public/web/WebInputEvent.h"
49 #include "third_party/WebKit/public/web/WebLocalFrame.h"
50 #include "third_party/WebKit/public/web/WebNavigationPolicy.h"
51 #include "third_party/WebKit/public/web/WebRemoteFrame.h"
52 #include "third_party/WebKit/public/web/WebRemoteFrameClient.h"
53 #include "third_party/WebKit/public/web/WebScriptSource.h"
54 #include "third_party/WebKit/public/web/WebSettings.h"
55 #include "third_party/WebKit/public/web/WebView.h"
56 #include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h"
57 #include "third_party/skia/include/core/SkCanvas.h"
58 #include "third_party/skia/include/core/SkColor.h"
59 #include "third_party/skia/include/core/SkDevice.h"
60 #include "ui/gfx/geometry/dip_util.h"
61 #include "ui/gfx/geometry/size.h"
62 #include "url/origin.h"
64 using mojo::AxProvider
;
66 using mojo::ServiceProviderPtr
;
67 using mojo::URLResponsePtr
;
69 using mojo::WeakBindToRequest
;
73 #define TEXT_INPUT_TYPE_ASSERT(NAME, Name) \
74 COMPILE_ASSERT(static_cast<int32>(TEXT_INPUT_TYPE_##NAME) == \
75 static_cast<int32>(blink::WebTextInputType##Name), \
76 text_input_type_should_match)
77 TEXT_INPUT_TYPE_ASSERT(NONE
, None
);
78 TEXT_INPUT_TYPE_ASSERT(TEXT
, Text
);
79 TEXT_INPUT_TYPE_ASSERT(PASSWORD
, Password
);
80 TEXT_INPUT_TYPE_ASSERT(SEARCH
, Search
);
81 TEXT_INPUT_TYPE_ASSERT(EMAIL
, Email
);
82 TEXT_INPUT_TYPE_ASSERT(NUMBER
, Number
);
83 TEXT_INPUT_TYPE_ASSERT(TELEPHONE
, Telephone
);
84 TEXT_INPUT_TYPE_ASSERT(URL
, URL
);
85 TEXT_INPUT_TYPE_ASSERT(DATE
, Date
);
86 TEXT_INPUT_TYPE_ASSERT(DATE_TIME
, DateTime
);
87 TEXT_INPUT_TYPE_ASSERT(DATE_TIME_LOCAL
, DateTimeLocal
);
88 TEXT_INPUT_TYPE_ASSERT(MONTH
, Month
);
89 TEXT_INPUT_TYPE_ASSERT(TIME
, Time
);
90 TEXT_INPUT_TYPE_ASSERT(WEEK
, Week
);
91 TEXT_INPUT_TYPE_ASSERT(TEXT_AREA
, TextArea
);
93 #define TEXT_INPUT_FLAG_ASSERT(NAME, Name) \
94 COMPILE_ASSERT(static_cast<int32>(TEXT_INPUT_FLAG_##NAME) == \
95 static_cast<int32>(blink::WebTextInputFlag##Name), \
96 text_input_flag_should_match)
97 TEXT_INPUT_FLAG_ASSERT(NONE
, None
);
98 TEXT_INPUT_FLAG_ASSERT(AUTO_COMPLETE_ON
, AutocompleteOn
);
99 TEXT_INPUT_FLAG_ASSERT(AUTO_COMPLETE_OFF
, AutocompleteOff
);
100 TEXT_INPUT_FLAG_ASSERT(AUTO_CORRECT_ON
, AutocorrectOn
);
101 TEXT_INPUT_FLAG_ASSERT(AUTO_CORRECT_OFF
, AutocorrectOff
);
102 TEXT_INPUT_FLAG_ASSERT(SPELL_CHECK_ON
, SpellcheckOn
);
103 TEXT_INPUT_FLAG_ASSERT(SPELL_CHECK_OFF
, SpellcheckOff
);
104 TEXT_INPUT_FLAG_ASSERT(AUTO_CAPITALIZE_NONE
, AutocapitalizeNone
);
105 TEXT_INPUT_FLAG_ASSERT(AUTO_CAPITALIZE_CHARACTERS
, AutocapitalizeCharacters
);
106 TEXT_INPUT_FLAG_ASSERT(AUTO_CAPITALIZE_WORDS
, AutocapitalizeWords
);
107 TEXT_INPUT_FLAG_ASSERT(AUTO_CAPITALIZE_SENTENCES
, AutocapitalizeSentences
);
110 struct TypeConverter
<TextInputType
, blink::WebTextInputType
> {
111 static TextInputType
Convert(const blink::WebTextInputType
& input
) {
112 return static_cast<TextInputType
>(input
);
118 namespace html_viewer
{
121 mandoline::NavigationTarget
WebNavigationPolicyToNavigationTarget(
122 blink::WebNavigationPolicy policy
) {
124 case blink::WebNavigationPolicyCurrentTab
:
125 return mandoline::NAVIGATION_TARGET_SOURCE_NODE
;
126 case blink::WebNavigationPolicyNewBackgroundTab
:
127 case blink::WebNavigationPolicyNewForegroundTab
:
128 case blink::WebNavigationPolicyNewWindow
:
129 case blink::WebNavigationPolicyNewPopup
:
130 return mandoline::NAVIGATION_TARGET_NEW_NODE
;
132 return mandoline::NAVIGATION_TARGET_DEFAULT
;
136 void ConfigureSettings(blink::WebSettings
* settings
) {
137 settings
->setCookieEnabled(true);
138 settings
->setDefaultFixedFontSize(13);
139 settings
->setDefaultFontSize(16);
140 settings
->setLoadsImagesAutomatically(true);
141 settings
->setJavaScriptEnabled(true);
144 HTMLFrame
* GetPreviousSibling(HTMLFrame
* frame
) {
145 DCHECK(frame
->parent());
146 auto iter
= std::find(frame
->parent()->children().begin(),
147 frame
->parent()->children().end(), frame
);
148 return (iter
== frame
->parent()->children().begin()) ? nullptr : *(--iter
);
151 bool CanNavigateLocally(blink::WebFrame
* frame
,
152 const blink::WebURLRequest
& request
) {
153 // If we have extraData() it means we already have the url response
154 // (presumably because we are being called via Navigate()). In that case we
155 // can go ahead and navigate locally.
156 if (request
.extraData())
159 // Otherwise we don't know if we're the right app to handle this request. Ask
160 // host to do the navigation for us.
166 HTMLFrame::HTMLFrame(const HTMLFrame::CreateParams
& params
)
167 : frame_tree_manager_(params
.manager
),
168 parent_(params
.parent
),
172 web_widget_(nullptr),
173 scope_(blink::WebTreeScopeType::Document
),
175 weak_factory_(this) {
177 parent_
->children_
.push_back(this);
180 void HTMLFrame::Init(
181 mojo::View
* local_view
,
182 const mojo::Map
<mojo::String
, mojo::Array
<uint8_t>>& properties
) {
183 if (local_view
&& local_view
->id() == id_
)
186 // Ignore return value and assume Document scope if scope isn't known.
187 FrameTreeScopeFromClientProperty(
188 GetValueFromClientProperties(kPropertyFrameTreeScope
, properties
),
191 blink::WebSandboxFlags sandbox_flags
= blink::WebSandboxFlags::None
;
192 FrameSandboxFlagsFromClientProperty(
193 GetValueFromClientProperties(kPropertyFrameSandboxFlags
, properties
),
197 CreateRootWebWidget();
198 // This is the root of the tree (aka the main frame).
199 // Expected order for creating webframes is:
200 // . Create local webframe (first webframe must always be local).
201 // . Set as main frame on WebView.
202 // . Swap to remote (if not local).
203 blink::WebLocalFrame
* local_web_frame
=
204 blink::WebLocalFrame::create(scope_
, this);
205 // We need to set the main frame before creating children so that state is
206 // properly set up in blink.
207 web_view()->setMainFrame(local_web_frame
);
208 const gfx::Size
size_in_pixels(local_view
->bounds().width
,
209 local_view
->bounds().height
);
210 const gfx::Size size_in_dips
= gfx::ConvertSizeToDIP(
211 local_view
->viewport_metrics().device_pixel_ratio
, size_in_pixels
);
212 web_widget_
->resize(size_in_dips
);
213 web_frame_
= local_web_frame
;
214 web_view()->setDeviceScaleFactor(global_state()->device_pixel_ratio());
215 if (id_
!= local_view
->id()) {
216 blink::WebRemoteFrame
* remote_web_frame
=
217 blink::WebRemoteFrame::create(scope_
, this);
218 local_web_frame
->swap(remote_web_frame
);
219 web_frame_
= remote_web_frame
;
221 } else if (local_view
&& id_
== local_view
->id()) {
222 // Frame represents the local frame, and it isn't the root of the tree.
223 HTMLFrame
* previous_sibling
= GetPreviousSibling(this);
224 blink::WebFrame
* previous_web_frame
=
225 previous_sibling
? previous_sibling
->web_frame() : nullptr;
226 DCHECK(!parent_
->IsLocal());
227 web_frame_
= parent_
->web_frame()->toWebRemoteFrame()->createLocalChild(
228 scope_
, FrameNameFromClientProperty(GetValueFromClientProperties(
229 kPropertyFrameName
, properties
)),
230 sandbox_flags
, this, previous_web_frame
);
231 CreateLocalRootWebWidget(web_frame_
->toWebLocalFrame());
232 } else if (!parent_
->IsLocal()) {
233 web_frame_
= parent_
->web_frame()->toWebRemoteFrame()->createRemoteChild(
234 scope_
, FrameNameFromClientProperty(GetValueFromClientProperties(
235 kPropertyFrameName
, properties
)),
236 sandbox_flags
, this);
238 // This is hit if we're asked to create a child frame of a local parent.
239 // This should never happen (if we create a local child we don't call
240 // Init(), and the frame server should not being creating child frames of
246 blink::WebRemoteFrame
* remote_web_frame
= web_frame_
->toWebRemoteFrame();
247 if (remote_web_frame
) {
248 remote_web_frame
->setReplicatedOrigin(FrameOriginFromClientProperty(
249 GetValueFromClientProperties(kPropertyFrameOrigin
, properties
)));
250 remote_web_frame
->setReplicatedName(FrameNameFromClientProperty(
251 GetValueFromClientProperties(kPropertyFrameName
, properties
)));
256 void HTMLFrame::Close() {
258 // Closing the root widget (WebView) implicitly detaches. For children
259 // (which have a WebFrameWidget) a detach() is required. Use a temporary
260 // as if 'this' is the root the call to web_widget_->close() deletes
262 const bool is_child
= parent_
!= nullptr;
263 web_widget_
->close();
265 web_frame_
->detach();
267 web_frame_
->detach();
271 const HTMLFrame
* HTMLFrame::FindFrame(uint32_t id
) const {
275 for (const HTMLFrame
* child
: children_
) {
276 const HTMLFrame
* match
= child
->FindFrame(id
);
283 blink::WebView
* HTMLFrame::web_view() {
284 return web_widget_
&& web_widget_
->isWebView()
285 ? static_cast<blink::WebView
*>(web_widget_
)
289 bool HTMLFrame::HasLocalDescendant() const {
293 for (HTMLFrame
* child
: children_
) {
294 if (child
->HasLocalDescendant())
300 HTMLFrame::~HTMLFrame() {
301 DCHECK(children_
.empty());
305 std::find(parent_
->children_
.begin(), parent_
->children_
.end(), this);
306 parent_
->children_
.erase(iter
);
310 frame_tree_manager_
->OnFrameDestroyed(this);
313 view_
->RemoveObserver(this);
314 if (view_
->view_manager()->GetRoot() == view_
)
315 delete view_
->view_manager();
321 void HTMLFrame::Bind(mandoline::FrameTreeServerPtr frame_tree_server
,
322 mojo::InterfaceRequest
<mandoline::FrameTreeClient
>
323 frame_tree_client_request
) {
325 // TODO(sky): error handling.
326 server_
= frame_tree_server
.Pass();
327 frame_tree_client_binding_
.reset(
328 new mojo::Binding
<mandoline::FrameTreeClient
>(
329 this, frame_tree_client_request
.Pass()));
332 void HTMLFrame::SetValueFromClientProperty(const std::string
& name
,
333 mojo::Array
<uint8_t> new_data
) {
337 // Only the name and origin dynamically change.
338 if (name
== kPropertyFrameOrigin
) {
339 web_frame_
->toWebRemoteFrame()->setReplicatedOrigin(
340 FrameOriginFromClientProperty(new_data
));
341 } else if (name
== kPropertyFrameName
) {
342 web_frame_
->toWebRemoteFrame()->setReplicatedName(
343 FrameNameFromClientProperty(new_data
));
347 bool HTMLFrame::IsLocal() const {
348 return web_frame_
->isWebLocalFrame();
351 HTMLFrame
* HTMLFrame::GetLocalRoot() {
352 HTMLFrame
* frame
= this;
353 while (frame
&& !frame
->delegate_
)
354 frame
= frame
->parent_
;
358 mojo::ApplicationImpl
* HTMLFrame::GetLocalRootApp() {
359 return GetLocalRoot()->delegate_
->GetApp();
362 void HTMLFrame::SetView(mojo::View
* view
) {
363 // TODO(sky): figure out way to cleanup view. In particular there may already
364 // be a view. This happens if we go from local->remote->local.
366 view_
->RemoveObserver(this);
368 view_
->AddObserver(this);
371 void HTMLFrame::CreateRootWebWidget() {
372 DCHECK(!web_widget_
);
373 blink::WebViewClient
* web_view_client
=
374 (view_
&& view_
->id() == id_
) ? this : nullptr;
375 web_widget_
= blink::WebView::create(web_view_client
);
377 InitializeWebWidget();
379 ConfigureSettings(web_view()->settings());
382 void HTMLFrame::CreateLocalRootWebWidget(blink::WebLocalFrame
* local_frame
) {
383 DCHECK(!web_widget_
);
385 web_widget_
= blink::WebFrameWidget::create(this, local_frame
);
387 InitializeWebWidget();
390 void HTMLFrame::InitializeWebWidget() {
391 // Creating the widget calls initializeLayerTreeView() to create the
392 // |web_layer_tree_view_impl_|. As we haven't yet assigned the |web_widget_|
393 // we have to set it here.
394 if (web_layer_tree_view_impl_
) {
395 web_layer_tree_view_impl_
->set_widget(web_widget_
);
396 web_layer_tree_view_impl_
->set_view(view_
);
397 UpdateWebViewSizeFromViewSize();
401 void HTMLFrame::UpdateFocus() {
402 if (!web_widget_
|| !view_
)
404 const bool is_focused
= view_
&& view_
->HasFocus();
405 web_widget_
->setFocus(is_focused
);
406 if (web_widget_
->isWebView())
407 static_cast<blink::WebView
*>(web_widget_
)->setIsActive(is_focused
);
410 void HTMLFrame::UpdateWebViewSizeFromViewSize() {
411 if (!web_widget_
|| !view_
)
414 const gfx::Size
size_in_pixels(view_
->bounds().width
, view_
->bounds().height
);
415 const gfx::Size size_in_dips
= gfx::ConvertSizeToDIP(
416 view_
->viewport_metrics().device_pixel_ratio
, size_in_pixels
);
418 blink::WebSize(size_in_dips
.width(), size_in_dips
.height()));
419 web_layer_tree_view_impl_
->setViewportSize(size_in_pixels
);
422 void HTMLFrame::SwapToRemote(const blink::WebURLRequest
& request
) {
424 mojo::URLRequestPtr url_request
= mojo::URLRequest::From(request
);
425 view_
->EmbedAllowingReembed(url_request
.Pass());
427 // TODO(sky): I tried swapping the frame types here, but that resulted in
428 // the view never getting sized. Figure out why.
429 base::MessageLoop::current()->PostTask(
431 base::Bind(&HTMLFrame::FinishSwapToRemote
, weak_factory_
.GetWeakPtr()));
434 void HTMLFrame::FinishSwapToRemote() {
435 if (web_frame_
->isWebRemoteFrame())
436 return; // We already did the swap.
438 blink::WebRemoteFrame
* remote_frame
=
439 blink::WebRemoteFrame::create(scope_
, this);
440 remote_frame
->initializeFromFrame(web_frame_
->toWebLocalFrame());
441 // swap() ends up calling us back and we then close the frame, which deletes
443 web_frame_
->swap(remote_frame
);
444 web_layer_
.reset(new WebLayerImpl(this));
445 remote_frame
->setRemoteWebLayer(web_layer_
.get());
446 web_frame_
= remote_frame
;
449 void HTMLFrame::SwapToLocal(
451 const mojo::Map
<mojo::String
, mojo::Array
<uint8_t>>& properties
) {
453 // It doesn't make sense for the root to swap to local.
456 blink::WebSandboxFlags sandbox_flags
= blink::WebSandboxFlags::None
;
457 FrameSandboxFlagsFromClientProperty(
458 GetValueFromClientProperties(kPropertyFrameSandboxFlags
, properties
),
460 blink::WebLocalFrame
* local_web_frame
=
461 blink::WebLocalFrame::create(blink::WebTreeScopeType::Document
, this);
462 local_web_frame
->initializeToReplaceRemoteFrame(
463 web_frame_
->toWebRemoteFrame(),
464 FrameNameFromClientProperty(
465 GetValueFromClientProperties(kPropertyFrameName
, properties
)),
467 // The swap() ends up calling to frameDetached() and deleting the old.
468 web_frame_
->swap(local_web_frame
);
469 web_frame_
= local_web_frame
;
472 HTMLFrame
* HTMLFrame::FindFrameWithWebFrame(blink::WebFrame
* web_frame
) {
473 if (web_frame_
== web_frame
)
475 for (HTMLFrame
* child_frame
: children_
) {
476 HTMLFrame
* result
= child_frame
->FindFrameWithWebFrame(web_frame
);
483 void HTMLFrame::FrameDetachedImpl(blink::WebFrame
* web_frame
) {
484 DCHECK_EQ(web_frame_
, web_frame
);
486 while (!children_
.empty()) {
487 HTMLFrame
* child
= children_
.front();
489 DCHECK(children_
.empty() || children_
.front() != child
);
492 if (web_frame
->parent())
493 web_frame
->parent()->removeChild(web_frame
);
498 void HTMLFrame::OnViewBoundsChanged(View
* view
,
499 const Rect
& old_bounds
,
500 const Rect
& new_bounds
) {
501 DCHECK_EQ(view
, view_
);
502 UpdateWebViewSizeFromViewSize();
505 void HTMLFrame::OnViewDestroyed(View
* view
) {
506 DCHECK_EQ(view
, view_
);
507 view_
->RemoveObserver(this);
512 void HTMLFrame::OnViewInputEvent(View
* view
, const mojo::EventPtr
& event
) {
513 if (event
->pointer_data
) {
514 // Blink expects coordintes to be in DIPs.
515 event
->pointer_data
->x
/= global_state()->device_pixel_ratio();
516 event
->pointer_data
->y
/= global_state()->device_pixel_ratio();
517 event
->pointer_data
->screen_x
/= global_state()->device_pixel_ratio();
518 event
->pointer_data
->screen_y
/= global_state()->device_pixel_ratio();
521 if (!touch_handler_
&& web_widget_
)
522 touch_handler_
.reset(new TouchHandler(web_widget_
));
524 if ((event
->action
== mojo::EVENT_TYPE_POINTER_DOWN
||
525 event
->action
== mojo::EVENT_TYPE_POINTER_UP
||
526 event
->action
== mojo::EVENT_TYPE_POINTER_CANCEL
||
527 event
->action
== mojo::EVENT_TYPE_POINTER_MOVE
) &&
528 event
->pointer_data
->kind
== mojo::POINTER_KIND_TOUCH
) {
529 touch_handler_
->OnTouchEvent(*event
);
536 scoped_ptr
<blink::WebInputEvent
> web_event
=
537 event
.To
<scoped_ptr
<blink::WebInputEvent
>>();
539 web_widget_
->handleInputEvent(*web_event
);
542 void HTMLFrame::OnViewFocusChanged(mojo::View
* gained_focus
,
543 mojo::View
* lost_focus
) {
547 void HTMLFrame::OnConnect(mandoline::FrameTreeServerPtr server
,
548 mojo::Array
<mandoline::FrameDataPtr
> frame_data
) {
549 // OnConnect() is only sent once, and has been received (by
550 // DocumentResourceWaiter) by the time we get here.
554 void HTMLFrame::OnFrameAdded(mandoline::FrameDataPtr frame_data
) {
555 frame_tree_manager_
->ProcessOnFrameAdded(this, frame_data
.Pass());
558 void HTMLFrame::OnFrameRemoved(uint32_t frame_id
) {
559 frame_tree_manager_
->ProcessOnFrameRemoved(this, frame_id
);
562 void HTMLFrame::OnFrameClientPropertyChanged(uint32_t frame_id
,
563 const mojo::String
& name
,
564 mojo::Array
<uint8_t> new_value
) {
565 frame_tree_manager_
->ProcessOnFrameClientPropertyChanged(this, frame_id
, name
,
569 blink::WebStorageNamespace
* HTMLFrame::createSessionStorageNamespace() {
570 return new WebStorageNamespaceImpl();
573 void HTMLFrame::didCancelCompositionOnSelectionChange() {
574 // TODO(penghuang): Update text input state.
577 void HTMLFrame::didChangeContents() {
578 // TODO(penghuang): Update text input state.
581 void HTMLFrame::initializeLayerTreeView() {
582 mojo::URLRequestPtr
request(mojo::URLRequest::New());
583 request
->url
= mojo::String::From("mojo:surfaces_service");
584 mojo::SurfacePtr surface
;
585 GetLocalRootApp()->ConnectToService(request
.Pass(), &surface
);
587 mojo::URLRequestPtr
request2(mojo::URLRequest::New());
588 request2
->url
= mojo::String::From("mojo:view_manager");
589 mojo::GpuPtr gpu_service
;
590 GetLocalRootApp()->ConnectToService(request2
.Pass(), &gpu_service
);
591 web_layer_tree_view_impl_
.reset(new WebLayerTreeViewImpl(
592 global_state()->compositor_thread(),
593 global_state()->gpu_memory_buffer_manager(),
594 global_state()->raster_thread_helper()->task_graph_runner(),
595 surface
.Pass(), gpu_service
.Pass()));
598 blink::WebLayerTreeView
* HTMLFrame::layerTreeView() {
599 return web_layer_tree_view_impl_
.get();
602 void HTMLFrame::resetInputMethod() {
603 // When this method gets called, WebWidgetClient implementation should
604 // reset the input method by cancelling any ongoing composition.
605 // TODO(penghuang): Reset IME.
608 void HTMLFrame::didHandleGestureEvent(const blink::WebGestureEvent
& event
,
609 bool eventCancelled
) {
610 // Called when a gesture event is handled.
614 if (event
.type
== blink::WebInputEvent::GestureTap
) {
615 const bool show_ime
= true;
616 UpdateTextInputState(show_ime
);
617 } else if (event
.type
== blink::WebInputEvent::GestureLongPress
) {
618 // Only show IME if the textfield contains text.
619 const bool show_ime
=
620 !web_view()->textInputInfo().value
.isEmpty();
621 UpdateTextInputState(show_ime
);
625 void HTMLFrame::didUpdateTextOfFocusedElementByNonUserInput() {
626 // Called when value of focused textfield gets dirty, e.g. value is
627 // modified by script, not by user input.
628 const bool show_ime
= false;
629 UpdateTextInputState(show_ime
);
632 void HTMLFrame::showImeIfNeeded() {
633 // Request the browser to show the IME for current input type.
634 const bool show_ime
= true;
635 UpdateTextInputState(show_ime
);
638 blink::WebMediaPlayer
* HTMLFrame::createMediaPlayer(
639 blink::WebLocalFrame
* frame
,
640 const blink::WebURL
& url
,
641 blink::WebMediaPlayerClient
* client
,
642 blink::WebMediaPlayerEncryptedMediaClient
* encrypted_client
,
643 blink::WebContentDecryptionModule
* initial_cdm
) {
644 return global_state()->media_factory()->CreateMediaPlayer(
645 frame
, url
, client
, encrypted_client
, initial_cdm
,
646 GetLocalRootApp()->shell());
649 blink::WebFrame
* HTMLFrame::createChildFrame(
650 blink::WebLocalFrame
* parent
,
651 blink::WebTreeScopeType scope
,
652 const blink::WebString
& frame_name
,
653 blink::WebSandboxFlags sandbox_flags
) {
654 DCHECK(IsLocal()); // Can't create children of remote frames.
655 DCHECK_EQ(parent
, web_frame_
);
656 DCHECK(view_
); // If we're local we have to have a view.
657 // Create the view that will house the frame now. We embed once we know the
658 // url (see decidePolicyForNavigation()).
659 mojo::View
* child_view
= view_
->view_manager()->CreateView();
660 mojo::Map
<mojo::String
, mojo::Array
<uint8_t>> client_properties
;
661 client_properties
.mark_non_null();
662 AddToClientPropertiesIfValid(kPropertyFrameName
,
663 FrameNameToClientProperty(frame_name
).Pass(),
665 AddToClientPropertiesIfValid(kPropertyFrameTreeScope
,
666 FrameTreeScopeToClientProperty(scope
).Pass(),
668 AddToClientPropertiesIfValid(
669 kPropertyFrameSandboxFlags
,
670 FrameSandboxFlagsToClientProperty(sandbox_flags
).Pass(),
673 child_view
->SetVisible(true);
674 view_
->AddChild(child_view
);
676 GetLocalRoot()->server_
->OnCreatedFrame(id_
, child_view
->id(),
677 client_properties
.Pass());
679 HTMLFrame::CreateParams
params(frame_tree_manager_
, this, child_view
->id());
680 HTMLFrame
* child_frame
= new HTMLFrame(params
);
681 child_frame
->scope_
= scope
;
683 child_frame
->SetView(child_view
);
685 blink::WebLocalFrame
* child_web_frame
=
686 blink::WebLocalFrame::create(scope
, child_frame
);
687 child_frame
->web_frame_
= child_web_frame
;
688 parent
->appendChild(child_web_frame
);
689 return child_web_frame
;
692 void HTMLFrame::frameDetached(blink::WebFrame
* web_frame
,
693 blink::WebFrameClient::DetachType type
) {
694 if (type
== blink::WebFrameClient::DetachType::Swap
) {
699 DCHECK(type
== blink::WebFrameClient::DetachType::Remove
);
700 FrameDetachedImpl(web_frame
);
703 blink::WebCookieJar
* HTMLFrame::cookieJar(blink::WebLocalFrame
* frame
) {
704 // TODO(darin): Blink does not fallback to the Platform provided WebCookieJar.
705 // Either it should, as it once did, or we should find another solution here.
706 return blink::Platform::current()->cookieJar();
709 blink::WebNavigationPolicy
HTMLFrame::decidePolicyForNavigation(
710 const NavigationPolicyInfo
& info
) {
711 if (parent_
&& parent_
->IsLocal() && GetLocalRoot() != this) {
712 // TODO(sky): this may be too early. I might want to wait to see if an embed
713 // actually happens, and swap then.
714 SwapToRemote(info
.urlRequest
);
715 return blink::WebNavigationPolicyIgnore
;
718 if (info
.frame
== web_frame() && this == frame_tree_manager_
->root_
&&
719 delegate_
&& delegate_
->ShouldNavigateLocallyInMainFrame()) {
720 return info
.defaultPolicy
;
723 if (CanNavigateLocally(info
.frame
, info
.urlRequest
))
724 return info
.defaultPolicy
;
726 mojo::URLRequestPtr url_request
= mojo::URLRequest::From(info
.urlRequest
);
727 GetLocalRoot()->server_
->RequestNavigate(
728 id(), WebNavigationPolicyToNavigationTarget(info
.defaultPolicy
),
731 return blink::WebNavigationPolicyIgnore
;
734 void HTMLFrame::didAddMessageToConsole(const blink::WebConsoleMessage
& message
,
735 const blink::WebString
& source_name
,
736 unsigned source_line
,
737 const blink::WebString
& stack_trace
) {
738 VLOG(1) << "[" << source_name
.utf8() << "(" << source_line
<< ")] "
739 << message
.text
.utf8();
742 void HTMLFrame::didFinishLoad(blink::WebLocalFrame
* frame
) {
743 if (GetLocalRoot() == this)
744 delegate_
->OnFrameDidFinishLoad();
747 void HTMLFrame::didNavigateWithinPage(blink::WebLocalFrame
* frame
,
748 const blink::WebHistoryItem
& history_item
,
749 blink::WebHistoryCommitType commit_type
) {
750 GetLocalRoot()->server_
->DidNavigateLocally(id_
,
751 history_item
.urlString().utf8());
754 blink::WebGeolocationClient
* HTMLFrame::geolocationClient() {
755 if (!geolocation_client_impl_
)
756 geolocation_client_impl_
.reset(new GeolocationClientImpl
);
757 return geolocation_client_impl_
.get();
760 blink::WebEncryptedMediaClient
* HTMLFrame::encryptedMediaClient() {
761 return global_state()->media_factory()->GetEncryptedMediaClient();
764 void HTMLFrame::didStartLoading(bool to_different_document
) {
765 GetLocalRoot()->server_
->LoadingStarted(id_
);
768 void HTMLFrame::didStopLoading() {
769 GetLocalRoot()->server_
->LoadingStopped(id_
);
772 void HTMLFrame::didChangeLoadProgress(double load_progress
) {
773 GetLocalRoot()->server_
->ProgressChanged(id_
, load_progress
);
776 void HTMLFrame::didChangeName(blink::WebLocalFrame
* frame
,
777 const blink::WebString
& name
) {
778 GetLocalRoot()->server_
->SetClientProperty(id_
, kPropertyFrameName
,
779 FrameNameToClientProperty(name
));
782 void HTMLFrame::didCommitProvisionalLoad(
783 blink::WebLocalFrame
* frame
,
784 const blink::WebHistoryItem
& item
,
785 blink::WebHistoryCommitType commit_type
) {
786 GetLocalRoot()->server_
->SetClientProperty(
787 id_
, kPropertyFrameOrigin
, FrameOriginToClientProperty(frame
));
790 void HTMLFrame::frameDetached(blink::WebRemoteFrameClient::DetachType type
) {
791 if (type
== blink::WebRemoteFrameClient::DetachType::Swap
) {
796 DCHECK(type
== blink::WebRemoteFrameClient::DetachType::Remove
);
797 FrameDetachedImpl(web_frame_
);
800 void HTMLFrame::UpdateTextInputState(bool show_ime
) {
801 blink::WebTextInputInfo new_info
= web_view()->textInputInfo();
802 // Only show IME if the focused element is editable.
803 show_ime
= show_ime
&& new_info
.type
!= blink::WebTextInputTypeNone
;
804 if (show_ime
|| text_input_info_
!= new_info
) {
805 text_input_info_
= new_info
;
806 mojo::TextInputStatePtr state
= mojo::TextInputState::New();
807 state
->type
= mojo::ConvertTo
<mojo::TextInputType
>(new_info
.type
);
808 state
->flags
= new_info
.flags
;
809 state
->text
= mojo::String::From(new_info
.value
.utf8());
810 state
->selection_start
= new_info
.selectionStart
;
811 state
->selection_end
= new_info
.selectionEnd
;
812 state
->composition_start
= new_info
.compositionStart
;
813 state
->composition_end
= new_info
.compositionEnd
;
815 view_
->SetImeVisibility(true, state
.Pass());
817 view_
->SetTextInputState(state
.Pass());
821 void HTMLFrame::postMessageEvent(blink::WebLocalFrame
* source_frame
,
822 blink::WebRemoteFrame
* target_frame
,
823 blink::WebSecurityOrigin target_origin
,
824 blink::WebDOMMessageEvent event
) {
828 void HTMLFrame::initializeChildFrame(const blink::WebRect
& frame_rect
,
829 float scale_factor
) {
830 // TODO(sky): frame_rect is in dips. Need to convert.
832 rect
.x
= frame_rect
.x
;
833 rect
.y
= frame_rect
.y
;
834 rect
.width
= frame_rect
.width
;
835 rect
.height
= frame_rect
.height
;
836 view_
->SetBounds(rect
);
839 void HTMLFrame::navigate(const blink::WebURLRequest
& request
,
840 bool should_replace_current_entry
) {
844 void HTMLFrame::reload(bool ignore_cache
, bool is_client_redirect
) {
848 void HTMLFrame::forwardInputEvent(const blink::WebInputEvent
* event
) {