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