Use common code to set HttpNetworkSession::Param pointers.
[chromium-blink-merge.git] / components / html_viewer / html_frame.cc
blob7699a33eaadaea51a89c3aa626a4b8796b532ce2
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"
7 #include <algorithm>
8 #include <limits>
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;
72 using mojo::Rect;
73 using mojo::ServiceProviderPtr;
74 using mojo::URLResponsePtr;
75 using mojo::View;
77 namespace html_viewer {
78 namespace {
80 mandoline::NavigationTargetType WebNavigationPolicyToNavigationTarget(
81 blink::WebNavigationPolicy policy) {
82 switch (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;
90 default:
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);
110 } // namespace
112 HTMLFrame::HTMLFrame(CreateParams* params)
113 : frame_tree_manager_(params->manager),
114 parent_(params->parent),
115 view_(nullptr),
116 id_(params->id),
117 web_frame_(nullptr),
118 web_widget_(nullptr),
119 delegate_(params->delegate),
120 weak_factory_(this) {
121 if (parent_)
122 parent_->children_.push_back(this);
124 if (params->view && params->view->id() == id_)
125 SetView(params->view);
127 SetReplicatedFrameStateFromClientProperties(params->properties, &state_);
129 if (!parent_) {
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;
153 } else {
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,
181 previous_web_frame);
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);
186 } else {
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
191 // this frame).
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);
200 if (!IsLocal()) {
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() {
210 if (web_widget_) {
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
214 // 'this'.
215 const bool is_child = parent_ != nullptr;
216 web_widget_->close();
217 if (is_child)
218 web_frame_->detach();
219 } else {
220 web_frame_->detach();
224 const HTMLFrame* HTMLFrame::FindFrame(uint32_t id) const {
225 if (id == id_)
226 return this;
228 for (const HTMLFrame* child : children_) {
229 const HTMLFrame* match = child->FindFrame(id);
230 if (match)
231 return match;
233 return nullptr;
236 blink::WebView* HTMLFrame::web_view() {
237 return web_widget_ && web_widget_->isWebView()
238 ? static_cast<blink::WebView*>(web_widget_)
239 : nullptr;
242 bool HTMLFrame::HasLocalDescendant() const {
243 if (IsLocal())
244 return true;
246 for (HTMLFrame* child : children_) {
247 if (child->HasLocalDescendant())
248 return true;
250 return false;
253 HTMLFrame::~HTMLFrame() {
254 DCHECK(children_.empty());
256 if (parent_) {
257 auto iter =
258 std::find(parent_->children_.begin(), parent_->children_.end(), this);
259 parent_->children_.erase(iter);
261 parent_ = nullptr;
263 frame_tree_manager_->OnFrameDestroyed(this);
265 if (view_) {
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) {
274 DCHECK(IsLocal());
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) {
284 if (IsLocal())
285 return;
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_;
305 return frame;
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();
315 if (local_root)
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) {
324 if (view_)
325 view_->RemoveObserver(this);
326 view_ = view;
327 if (view_)
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_);
344 DCHECK(IsLocal());
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_)
363 return;
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_)
372 return;
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);
377 web_widget_->resize(
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() {
383 DCHECK(IsLocal());
385 HTMLFrameDelegate* delegate = delegate_;
386 delegate_ = nullptr;
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
392 // it.
393 web_frame_->swap(remote_frame);
394 // TODO(sky): this isn't quite right, but WebLayerImpl is temporary.
395 if (owned_view_) {
396 web_layer_.reset(
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;
405 SetView(nullptr);
406 if (delegate)
407 delegate->OnFrameSwappedToRemote();
410 void HTMLFrame::SwapToLocal(
411 HTMLFrameDelegate* delegate,
412 mojo::View* view,
413 const mojo::Map<mojo::String, mojo::Array<uint8_t>>& properties) {
414 CHECK(!IsLocal());
415 // It doesn't make sense for the root to swap to local.
416 CHECK(parent_);
417 delegate_ = delegate;
418 SetView(view);
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;
428 web_layer_.reset();
431 HTMLFrame* HTMLFrame::FindFrameWithWebFrame(blink::WebFrame* web_frame) {
432 if (web_frame_ == web_frame)
433 return this;
434 for (HTMLFrame* child_frame : children_) {
435 HTMLFrame* result = child_frame->FindFrameWithWebFrame(web_frame);
436 if (result)
437 return result;
439 return nullptr;
442 void HTMLFrame::FrameDetachedImpl(blink::WebFrame* web_frame) {
443 DCHECK_EQ(web_frame_, web_frame);
445 while (!children_.empty()) {
446 HTMLFrame* child = children_.front();
447 child->Close();
448 DCHECK(children_.empty() || children_.front() != child);
451 if (web_frame->parent())
452 web_frame->parent()->removeChild(web_frame);
454 delete this;
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);
467 view_ = nullptr;
468 Close();
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);
489 return;
492 if (!web_widget_)
493 return;
495 scoped_ptr<blink::WebInputEvent> web_event =
496 event.To<scoped_ptr<blink::WebInputEvent>>();
497 if (web_event)
498 web_widget_->handleInputEvent(*web_event);
501 void HTMLFrame::OnViewFocusChanged(mojo::View* gained_focus,
502 mojo::View* lost_focus) {
503 UpdateFocus();
506 void HTMLFrame::OnConnect(mandoline::FrameTreeServerPtr server,
507 uint32_t change_id,
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.
511 NOTREACHED();
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,
527 new_value.Pass());
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";
539 return;
542 if (!target->IsLocal()) {
543 DVLOG(1) << "Target for PostMessage is not lot local";
544 return;
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(
562 "message",
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,
576 msg_event);
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();
589 callback.Run();
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.
634 if (eventCancelled)
635 return;
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(&params);
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) {
708 web_frame->close();
709 return;
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_,
737 url_request.Pass());
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());
754 recorded = true;
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());
775 recorded = true;
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) {
803 state_.name = 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) {
819 web_frame_->close();
820 return;
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;
841 if (show_ime)
842 view_->SetImeVisibility(true, state.Pass());
843 else
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,
875 frame_rect.height);
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_,
889 url_request.Pass());
892 void HTMLFrame::reload(bool ignore_cache, bool is_client_redirect) {
893 NOTIMPLEMENTED();
896 void HTMLFrame::forwardInputEvent(const blink::WebInputEvent* event) {
897 NOTIMPLEMENTED();
900 } // namespace mojo