Allow only one bookmark to be added for multiple fast starring
[chromium-blink-merge.git] / components / html_viewer / html_frame.cc
blobaf7ed2884f4880f4efb7cafac86c18670f454c84
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_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;
65 using mojo::Rect;
66 using mojo::ServiceProviderPtr;
67 using mojo::URLResponsePtr;
68 using mojo::View;
69 using mojo::WeakBindToRequest;
71 namespace mojo {
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);
109 template <>
110 struct TypeConverter<TextInputType, blink::WebTextInputType> {
111 static TextInputType Convert(const blink::WebTextInputType& input) {
112 return static_cast<TextInputType>(input);
116 } // namespace mojo
118 namespace html_viewer {
119 namespace {
121 mandoline::NavigationTarget WebNavigationPolicyToNavigationTarget(
122 blink::WebNavigationPolicy policy) {
123 switch (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;
131 default:
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())
157 return true;
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.
161 return false;
164 } // namespace
166 HTMLFrame::HTMLFrame(const HTMLFrame::CreateParams& params)
167 : frame_tree_manager_(params.manager),
168 parent_(params.parent),
169 view_(nullptr),
170 id_(params.id),
171 web_frame_(nullptr),
172 web_widget_(nullptr),
173 scope_(blink::WebTreeScopeType::Document),
174 delegate_(nullptr),
175 weak_factory_(this) {
176 if (parent_)
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_)
184 SetView(local_view);
186 // Ignore return value and assume Document scope if scope isn't known.
187 FrameTreeScopeFromClientProperty(
188 GetValueFromClientProperties(kPropertyFrameTreeScope, properties),
189 &scope_);
191 blink::WebSandboxFlags sandbox_flags = blink::WebSandboxFlags::None;
192 FrameSandboxFlagsFromClientProperty(
193 GetValueFromClientProperties(kPropertyFrameSandboxFlags, properties),
194 &sandbox_flags);
196 if (!parent_) {
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);
237 } else {
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
241 // this frame).
242 NOTREACHED();
245 if (!IsLocal()) {
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() {
257 if (web_widget_) {
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
261 // 'this'.
262 const bool is_child = parent_ != nullptr;
263 web_widget_->close();
264 if (is_child)
265 web_frame_->detach();
266 } else {
267 web_frame_->detach();
271 const HTMLFrame* HTMLFrame::FindFrame(uint32_t id) const {
272 if (id == id_)
273 return this;
275 for (const HTMLFrame* child : children_) {
276 const HTMLFrame* match = child->FindFrame(id);
277 if (match)
278 return match;
280 return nullptr;
283 blink::WebView* HTMLFrame::web_view() {
284 return web_widget_ && web_widget_->isWebView()
285 ? static_cast<blink::WebView*>(web_widget_)
286 : nullptr;
289 bool HTMLFrame::HasLocalDescendant() const {
290 if (IsLocal())
291 return true;
293 for (HTMLFrame* child : children_) {
294 if (child->HasLocalDescendant())
295 return true;
297 return false;
300 HTMLFrame::~HTMLFrame() {
301 DCHECK(children_.empty());
303 if (parent_) {
304 auto iter =
305 std::find(parent_->children_.begin(), parent_->children_.end(), this);
306 parent_->children_.erase(iter);
308 parent_ = nullptr;
310 frame_tree_manager_->OnFrameDestroyed(this);
312 if (view_) {
313 view_->RemoveObserver(this);
314 if (view_->view_manager()->GetRoot() == view_)
315 delete view_->view_manager();
316 else
317 view_->Destroy();
321 void HTMLFrame::Bind(mandoline::FrameTreeServerPtr frame_tree_server,
322 mojo::InterfaceRequest<mandoline::FrameTreeClient>
323 frame_tree_client_request) {
324 DCHECK(IsLocal());
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) {
334 if (IsLocal())
335 return;
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_;
355 return frame;
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.
365 if (view_)
366 view_->RemoveObserver(this);
367 view_ = view;
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_);
384 DCHECK(IsLocal());
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_)
403 return;
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_)
412 return;
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);
417 web_widget_->resize(
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) {
423 CHECK(IsLocal());
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(
430 FROM_HERE,
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
442 // it.
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(
450 mojo::View* view,
451 const mojo::Map<mojo::String, mojo::Array<uint8_t>>& properties) {
452 CHECK(!IsLocal());
453 // It doesn't make sense for the root to swap to local.
454 CHECK(parent_);
455 SetView(view);
456 blink::WebSandboxFlags sandbox_flags = blink::WebSandboxFlags::None;
457 FrameSandboxFlagsFromClientProperty(
458 GetValueFromClientProperties(kPropertyFrameSandboxFlags, properties),
459 &sandbox_flags);
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)),
466 sandbox_flags);
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)
474 return this;
475 for (HTMLFrame* child_frame : children_) {
476 HTMLFrame* result = child_frame->FindFrameWithWebFrame(web_frame);
477 if (result)
478 return result;
480 return nullptr;
483 void HTMLFrame::FrameDetachedImpl(blink::WebFrame* web_frame) {
484 DCHECK_EQ(web_frame_, web_frame);
486 while (!children_.empty()) {
487 HTMLFrame* child = children_.front();
488 child->Close();
489 DCHECK(children_.empty() || children_.front() != child);
492 if (web_frame->parent())
493 web_frame->parent()->removeChild(web_frame);
495 delete this;
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);
508 view_ = nullptr;
509 Close();
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);
530 return;
533 if (!web_widget_)
534 return;
536 scoped_ptr<blink::WebInputEvent> web_event =
537 event.To<scoped_ptr<blink::WebInputEvent>>();
538 if (web_event)
539 web_widget_->handleInputEvent(*web_event);
542 void HTMLFrame::OnViewFocusChanged(mojo::View* gained_focus,
543 mojo::View* lost_focus) {
544 UpdateFocus();
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.
551 NOTREACHED();
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,
566 new_value.Pass());
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.
611 if (eventCancelled)
612 return;
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(),
664 &client_properties);
665 AddToClientPropertiesIfValid(kPropertyFrameTreeScope,
666 FrameTreeScopeToClientProperty(scope).Pass(),
667 &client_properties);
668 AddToClientPropertiesIfValid(
669 kPropertyFrameSandboxFlags,
670 FrameSandboxFlagsToClientProperty(sandbox_flags).Pass(),
671 &client_properties);
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) {
695 web_frame->close();
696 return;
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),
729 url_request.Pass());
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) {
792 web_frame_->close();
793 return;
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;
814 if (show_ime)
815 view_->SetImeVisibility(true, state.Pass());
816 else
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) {
825 NOTIMPLEMENTED();
828 void HTMLFrame::initializeChildFrame(const blink::WebRect& frame_rect,
829 float scale_factor) {
830 // TODO(sky): frame_rect is in dips. Need to convert.
831 mojo::Rect rect;
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) {
841 NOTIMPLEMENTED();
844 void HTMLFrame::reload(bool ignore_cache, bool is_client_redirect) {
845 NOTIMPLEMENTED();
848 void HTMLFrame::forwardInputEvent(const blink::WebInputEvent* event) {
849 NOTIMPLEMENTED();
852 } // namespace mojo