Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: components/html_viewer/html_frame.cc

Issue 1677293002: Bye bye Mandoline (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: moar Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/html_viewer/html_frame.h ('k') | components/html_viewer/html_frame_apptest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "components/html_viewer/html_frame.h"
6
7 #include <stddef.h>
8 #include <algorithm>
9 #include <limits>
10 #include <utility>
11
12 #include "base/bind.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/stl_util.h"
15 #include "base/strings/string_util.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "cc/blink/web_layer_impl.h"
18 #include "cc/surfaces/surface_id.h"
19 #include "components/html_viewer/ax_provider_impl.h"
20 #include "components/html_viewer/blink_basic_type_converters.h"
21 #include "components/html_viewer/blink_find_type_converters.h"
22 #include "components/html_viewer/blink_text_input_type_converters.h"
23 #include "components/html_viewer/blink_url_request_type_converters.h"
24 #include "components/html_viewer/devtools_agent_impl.h"
25 #include "components/html_viewer/geolocation_client_impl.h"
26 #include "components/html_viewer/global_state.h"
27 #include "components/html_viewer/html_factory.h"
28 #include "components/html_viewer/html_frame_delegate.h"
29 #include "components/html_viewer/html_frame_properties.h"
30 #include "components/html_viewer/html_frame_tree_manager.h"
31 #include "components/html_viewer/html_widget.h"
32 #include "components/html_viewer/media_factory.h"
33 #include "components/html_viewer/stats_collection_controller.h"
34 #include "components/html_viewer/touch_handler.h"
35 #include "components/html_viewer/web_layer_tree_view_impl.h"
36 #include "components/html_viewer/web_storage_namespace_impl.h"
37 #include "components/html_viewer/web_url_loader_impl.h"
38 #include "components/mus/public/cpp/scoped_window_ptr.h"
39 #include "components/mus/public/cpp/window.h"
40 #include "components/mus/public/cpp/window_tree_connection.h"
41 #include "components/mus/ws/ids.h"
42 #include "mojo/common/common_type_converters.h"
43 #include "mojo/converters/blink/blink_input_events_type_converters.h"
44 #include "mojo/converters/geometry/geometry_type_converters.h"
45 #include "mojo/shell/public/cpp/shell.h"
46 #include "third_party/WebKit/public/platform/Platform.h"
47 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
48 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
49 #include "third_party/WebKit/public/platform/WebSize.h"
50 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
51 #include "third_party/WebKit/public/web/WebDocument.h"
52 #include "third_party/WebKit/public/web/WebElement.h"
53 #include "third_party/WebKit/public/web/WebFindOptions.h"
54 #include "third_party/WebKit/public/web/WebFrameOwnerProperties.h"
55 #include "third_party/WebKit/public/web/WebInputEvent.h"
56 #include "third_party/WebKit/public/web/WebKit.h"
57 #include "third_party/WebKit/public/web/WebLocalFrame.h"
58 #include "third_party/WebKit/public/web/WebNavigationPolicy.h"
59 #include "third_party/WebKit/public/web/WebRemoteFrame.h"
60 #include "third_party/WebKit/public/web/WebRemoteFrameClient.h"
61 #include "third_party/WebKit/public/web/WebScriptSource.h"
62 #include "third_party/WebKit/public/web/WebView.h"
63 #include "ui/gfx/geometry/dip_util.h"
64 #include "ui/gfx/geometry/size.h"
65 #include "url/gurl.h"
66 #include "url/origin.h"
67 #include "url/url_constants.h"
68
69 using mojo::AxProvider;
70 using mojo::Rect;
71 using mojo::ServiceProviderPtr;
72 using mojo::URLResponsePtr;
73 using web_view::mojom::HTMLMessageEvent;
74 using web_view::mojom::HTMLMessageEventPtr;
75
76 namespace html_viewer {
77 namespace {
78
79 const size_t kMaxTitleChars = 4 * 1024;
80
81 web_view::mojom::NavigationTargetType WebNavigationPolicyToNavigationTarget(
82 blink::WebNavigationPolicy policy) {
83 switch (policy) {
84 case blink::WebNavigationPolicyCurrentTab:
85 return web_view::mojom::NavigationTargetType::EXISTING_FRAME;
86 case blink::WebNavigationPolicyNewBackgroundTab:
87 case blink::WebNavigationPolicyNewForegroundTab:
88 case blink::WebNavigationPolicyNewWindow:
89 case blink::WebNavigationPolicyNewPopup:
90 return web_view::mojom::NavigationTargetType::NEW_FRAME;
91 default:
92 return web_view::mojom::NavigationTargetType::NO_PREFERENCE;
93 }
94 }
95
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);
101 }
102
103 // See surface_layer.h for a description of this callback.
104 void SatisfyCallback(cc::SurfaceSequence sequence) {
105 // TODO(fsamuel): Implement this.
106 }
107
108 // See surface_layer.h for a description of this callback.
109 void RequireCallback(cc::SurfaceId surface_id,
110 cc::SurfaceSequence sequence) {
111 // TODO(fsamuel): Implement this.
112 }
113
114 } // namespace
115
116 HTMLFrame::HTMLFrame(CreateParams* params)
117 : frame_tree_manager_(params->manager),
118 parent_(params->parent),
119 window_(nullptr),
120 id_(params->id),
121 web_frame_(nullptr),
122 delegate_(params->delegate),
123 pending_navigation_(false),
124 weak_factory_(this) {
125 TRACE_EVENT0("html_viewer", "HTMLFrame::HTMLFrame");
126 if (parent_)
127 parent_->children_.push_back(this);
128
129 if (params->window && params->window->id() == id_)
130 SetWindow(params->window);
131
132 SetReplicatedFrameStateFromClientProperties(params->properties, &state_);
133
134 if (!parent_) {
135 CreateRootWebWidget();
136
137 // This is the root of the tree (aka the main frame).
138 // Expected order for creating webframes is:
139 // . Create local webframe (first webframe must always be local).
140 // . Set as main frame on WebView.
141 // . Swap to remote (if not local).
142 blink::WebLocalFrame* local_web_frame =
143 blink::WebLocalFrame::create(state_.tree_scope, this);
144 // We need to set the main frame before creating children so that state is
145 // properly set up in blink.
146 web_view()->setMainFrame(local_web_frame);
147
148 // The resize and setDeviceScaleFactor() needs to be after setting the main
149 // frame.
150 const gfx::Size size_in_pixels(params->window->bounds().size());
151 const gfx::Size size_in_dips = gfx::ConvertSizeToDIP(
152 params->window->viewport_metrics().device_pixel_ratio, size_in_pixels);
153 web_view()->resize(size_in_dips);
154 web_frame_ = local_web_frame;
155 web_view()->setDeviceScaleFactor(global_state()->device_pixel_ratio());
156 if (id_ != params->window->id()) {
157 blink::WebRemoteFrame* remote_web_frame =
158 blink::WebRemoteFrame::create(state_.tree_scope, this);
159 local_web_frame->swap(remote_web_frame);
160 web_frame_ = remote_web_frame;
161 } else {
162 // Setup a DevTools agent if this is the local main frame and the browser
163 // side has set relevant client properties.
164 mojo::Array<uint8_t> devtools_id =
165 GetValueFromClientProperties("devtools-id", params->properties);
166 if (!devtools_id.is_null()) {
167 mojo::Array<uint8_t> devtools_state =
168 GetValueFromClientProperties("devtools-state", params->properties);
169 std::string devtools_state_str = devtools_state.To<std::string>();
170 devtools_agent_.reset(new DevToolsAgentImpl(
171 web_frame_->toWebLocalFrame(), devtools_id.To<std::string>(),
172 devtools_state.is_null() ? nullptr : &devtools_state_str));
173 }
174
175 // Collect startup perf data for local main frames in test environments.
176 // Child frames aren't tracked, and tracking remote frames is redundant.
177 startup_performance_data_collector_ =
178 StatsCollectionController::Install(web_frame_, GetShell());
179 }
180 } else if (!params->is_local_create_child && params->window &&
181 id_ == params->window->id()) {
182 // Frame represents the local frame, and it isn't the root of the tree.
183 HTMLFrame* previous_sibling = GetPreviousSibling(this);
184 blink::WebFrame* previous_web_frame =
185 previous_sibling ? previous_sibling->web_frame() : nullptr;
186 CHECK(!parent_->IsLocal());
187 web_frame_ = parent_->web_frame()->toWebRemoteFrame()->createLocalChild(
188 state_.tree_scope, state_.name, state_.sandbox_flags, this,
189 previous_web_frame,
190 // TODO(lazyboy): Replicate WebFrameOwnerProperties where needed.
191 blink::WebFrameOwnerProperties());
192 CreateLocalRootWebWidget(web_frame_->toWebLocalFrame());
193 } else if (!parent_->IsLocal()) {
194 web_frame_ = parent_->web_frame()->toWebRemoteFrame()->createRemoteChild(
195 state_.tree_scope, state_.name, state_.sandbox_flags, this);
196 } else {
197 CHECK(params->is_local_create_child);
198
199 blink::WebLocalFrame* child_web_frame =
200 blink::WebLocalFrame::create(state_.tree_scope, this);
201 web_frame_ = child_web_frame;
202 parent_->web_frame_->appendChild(child_web_frame);
203 }
204
205 DVLOG(2) << "HTMLFrame init this=" << this << " id=" << id_
206 << " local=" << IsLocal()
207 << " parent=" << (parent_ ? parent_->id_ : 0u);
208
209 if (!IsLocal()) {
210 blink::WebRemoteFrame* remote_web_frame = web_frame_->toWebRemoteFrame();
211 if (remote_web_frame) {
212 remote_web_frame->setReplicatedOrigin(state_.origin);
213 remote_web_frame->setReplicatedName(state_.name);
214 }
215 }
216 }
217
218 void HTMLFrame::Close() {
219 if (GetWebWidget()) {
220 // Closing the root widget (WebView) implicitly detaches. For children
221 // (which have a WebFrameWidget) a detach() is required. Use a temporary
222 // as if 'this' is the root the call to GetWebWidget()->close() deletes
223 // 'this'.
224 const bool is_child = parent_ != nullptr;
225 GetWebWidget()->close();
226 if (is_child)
227 web_frame_->detach();
228 } else {
229 web_frame_->detach();
230 }
231 }
232
233 const HTMLFrame* HTMLFrame::FindFrame(uint32_t id) const {
234 if (id == id_)
235 return this;
236
237 for (const HTMLFrame* child : children_) {
238 const HTMLFrame* match = child->FindFrame(id);
239 if (match)
240 return match;
241 }
242 return nullptr;
243 }
244
245 blink::WebView* HTMLFrame::web_view() {
246 blink::WebWidget* web_widget =
247 html_widget_ ? html_widget_->GetWidget() : nullptr;
248 return web_widget && web_widget->isWebView()
249 ? static_cast<blink::WebView*>(web_widget)
250 : nullptr;
251 }
252
253 blink::WebWidget* HTMLFrame::GetWebWidget() {
254 return html_widget_ ? html_widget_->GetWidget() : nullptr;
255 }
256
257 bool HTMLFrame::IsLocal() const {
258 return web_frame_->isWebLocalFrame();
259 }
260
261 bool HTMLFrame::HasLocalDescendant() const {
262 if (IsLocal())
263 return true;
264
265 for (HTMLFrame* child : children_) {
266 if (child->HasLocalDescendant())
267 return true;
268 }
269 return false;
270 }
271
272 void HTMLFrame::LoadRequest(const blink::WebURLRequest& request,
273 base::TimeTicks navigation_start_time) {
274 TRACE_EVENT1("html_viewer", "HTMLFrame::LoadRequest",
275 "url", request.url().string().utf8());
276
277 DCHECK(IsLocal());
278
279 DVLOG(2) << "HTMLFrame::LoadRequest this=" << this << " id=" << id_
280 << " URL=" << GURL(request.url());
281
282 pending_navigation_ = false;
283 navigation_start_time_ = navigation_start_time;
284 web_frame_->toWebLocalFrame()->loadRequest(request);
285 }
286
287 HTMLFrame::~HTMLFrame() {
288 DVLOG(2) << "~HTMLFrame this=" << this << " id=" << id_;
289
290 DCHECK(children_.empty());
291
292 if (parent_) {
293 auto iter =
294 std::find(parent_->children_.begin(), parent_->children_.end(), this);
295 parent_->children_.erase(iter);
296 }
297 parent_ = nullptr;
298
299 frame_tree_manager_->OnFrameDestroyed(this);
300
301 if (delegate_)
302 delegate_->OnFrameDestroyed();
303
304 if (window_) {
305 window_->RemoveObserver(this);
306 mus::ScopedWindowPtr::DeleteWindowOrWindowManager(window_);
307 }
308 }
309
310 blink::WebMediaPlayer* HTMLFrame::createMediaPlayer(
311 blink::WebLocalFrame* frame,
312 blink::WebMediaPlayer::LoadType load_type,
313 const blink::WebURL& url,
314 blink::WebMediaPlayerClient* client,
315 blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
316 blink::WebContentDecryptionModule* initial_cdm,
317 const blink::WebString& sink_id,
318 blink::WebMediaSession* media_session) {
319 return global_state()->media_factory()->CreateMediaPlayer(
320 frame, url, client, encrypted_client, initial_cdm, GetShell());
321 }
322
323 blink::WebFrame* HTMLFrame::createChildFrame(
324 blink::WebLocalFrame* parent,
325 blink::WebTreeScopeType scope,
326 const blink::WebString& frame_name,
327 blink::WebSandboxFlags sandbox_flags,
328 const blink::WebFrameOwnerProperties& frame_owner_properties) {
329 DCHECK(IsLocal()); // Can't create children of remote frames.
330 DCHECK_EQ(parent, web_frame_);
331 DCHECK(window_); // If we're local we have to have a window.
332 // Create the window that will house the frame now. We embed once we know the
333 // url (see decidePolicyForNavigation()).
334 mus::Window* child_window = window_->connection()->NewWindow();
335 ReplicatedFrameState child_state;
336 child_state.name = frame_name;
337 child_state.tree_scope = scope;
338 child_state.sandbox_flags = sandbox_flags;
339 mojo::Map<mojo::String, mojo::Array<uint8_t>> client_properties;
340 client_properties.mark_non_null();
341 ClientPropertiesFromReplicatedFrameState(child_state, &client_properties);
342
343 child_window->SetVisible(true);
344 window_->AddChild(child_window);
345
346 HTMLFrame::CreateParams params(frame_tree_manager_, this, child_window->id(),
347 child_window, client_properties, nullptr);
348 params.is_local_create_child = true;
349 HTMLFrame* child_frame = GetFirstAncestorWithDelegate()
350 ->delegate_->GetHTMLFactory()
351 ->CreateHTMLFrame(&params);
352 child_frame->owned_window_.reset(new mus::ScopedWindowPtr(child_window));
353
354 web_view::mojom::FrameClientPtr client_ptr;
355 child_frame->frame_client_binding_.reset(
356 new mojo::Binding<web_view::mojom::FrameClient>(
357 child_frame, mojo::GetProxy(&client_ptr)));
358 server_->OnCreatedFrame(GetProxy(&(child_frame->server_)),
359 std::move(client_ptr), child_window->id(),
360 std::move(client_properties));
361 return child_frame->web_frame_;
362 }
363
364 void HTMLFrame::frameDetached(blink::WebFrame* web_frame,
365 blink::WebFrameClient::DetachType type) {
366 if (type == blink::WebFrameClient::DetachType::Swap) {
367 web_frame->close();
368 return;
369 }
370
371 DCHECK(type == blink::WebFrameClient::DetachType::Remove);
372 FrameDetachedImpl(web_frame);
373 }
374
375 blink::WebCookieJar* HTMLFrame::cookieJar(blink::WebLocalFrame* frame) {
376 // TODO(darin): Blink does not fallback to the Platform provided WebCookieJar.
377 // Either it should, as it once did, or we should find another solution here.
378 return blink::Platform::current()->cookieJar();
379 }
380
381 blink::WebNavigationPolicy HTMLFrame::decidePolicyForNavigation(
382 const NavigationPolicyInfo& info) {
383 // If we have extraData() it means we already have the url response
384 // (presumably because we are being called via Navigate()). In that case we
385 // can go ahead and navigate locally.
386 if (info.urlRequest.extraData()) {
387 DCHECK_EQ(blink::WebNavigationPolicyCurrentTab, info.defaultPolicy);
388 return blink::WebNavigationPolicyCurrentTab;
389 }
390
391 // about:blank is treated as the same origin and is always allowed for frames.
392 if (parent_ && info.urlRequest.url() == GURL(url::kAboutBlankURL) &&
393 info.defaultPolicy == blink::WebNavigationPolicyCurrentTab) {
394 return blink::WebNavigationPolicyCurrentTab;
395 }
396
397 // Ask the Frame to handle the navigation. Returning
398 // WebNavigationPolicyHandledByClient to inform blink that the navigation is
399 // being handled.
400 DVLOG(2) << "HTMLFrame::decidePolicyForNavigation calls "
401 << "Frame::RequestNavigate this=" << this << " id=" << id_
402 << " URL=" << GURL(info.urlRequest.url());
403
404 mojo::URLRequestPtr url_request = mojo::URLRequest::From(info.urlRequest);
405 url_request->originating_time_ticks =
406 base::TimeTicks::Now().ToInternalValue();
407 server_->RequestNavigate(
408 WebNavigationPolicyToNavigationTarget(info.defaultPolicy), id_,
409 std::move(url_request));
410
411 // TODO(yzshen): crbug.com/532556 If the server side drops the request,
412 // this frame will be in permenant-loading state. We should send a
413 // notification to mark this frame as not loading in that case. We also need
414 // to better keep track of multiple pending navigations.
415 pending_navigation_ = true;
416 return blink::WebNavigationPolicyHandledByClient;
417 }
418
419 bool HTMLFrame::hasPendingNavigation(blink::WebLocalFrame* frame) {
420 return pending_navigation_;
421 }
422
423 void HTMLFrame::didHandleOnloadEvents(blink::WebLocalFrame* frame) {
424 DVLOG(2) << "XXX HTMLFrame::didHandleOnloadEvents id=" << id_;
425 static bool recorded = false;
426 if (!recorded && startup_performance_data_collector_) {
427 startup_performance_data_collector_->SetFirstWebContentsMainFrameLoadTicks(
428 base::TimeTicks::Now().ToInternalValue());
429 recorded = true;
430 }
431 }
432
433 void HTMLFrame::didAddMessageToConsole(const blink::WebConsoleMessage& message,
434 const blink::WebString& source_name,
435 unsigned source_line,
436 const blink::WebString& stack_trace) {
437 VLOG(1) << "[" << source_name.utf8() << "(" << source_line << ")] "
438 << message.text.utf8();
439 }
440
441 void HTMLFrame::didFinishLoad(blink::WebLocalFrame* frame) {
442 if (GetFirstAncestorWithDelegate() == this)
443 delegate_->OnFrameDidFinishLoad();
444 }
445
446 void HTMLFrame::didNavigateWithinPage(blink::WebLocalFrame* frame,
447 const blink::WebHistoryItem& history_item,
448 blink::WebHistoryCommitType commit_type) {
449 server_->DidNavigateLocally(history_item.urlString().utf8());
450 }
451
452 blink::WebGeolocationClient* HTMLFrame::geolocationClient() {
453 if (!geolocation_client_impl_)
454 geolocation_client_impl_.reset(new GeolocationClientImpl);
455 return geolocation_client_impl_.get();
456 }
457
458 blink::WebEncryptedMediaClient* HTMLFrame::encryptedMediaClient() {
459 return global_state()->media_factory()->GetEncryptedMediaClient();
460 }
461
462 void HTMLFrame::didStartLoading(bool to_different_document) {
463 server_->LoadingStateChanged(true, 0.0);
464 }
465
466 void HTMLFrame::didStopLoading() {
467 server_->LoadingStateChanged(false, 1.0);
468 }
469
470 void HTMLFrame::didChangeLoadProgress(double load_progress) {
471 server_->LoadingStateChanged(true, load_progress);
472 }
473
474 void HTMLFrame::dispatchLoad() {
475 // According to comments of WebFrameClient::dispatchLoad(), this should only
476 // be called when the parent frame is remote.
477 DCHECK(parent_ && !parent_->IsLocal());
478 server_->DispatchLoadEventToParent();
479 }
480
481 void HTMLFrame::didChangeName(blink::WebLocalFrame* frame,
482 const blink::WebString& name) {
483 state_.name = name;
484 server_->SetClientProperty(kPropertyFrameName,
485 FrameNameToClientProperty(name));
486 }
487
488 void HTMLFrame::didCommitProvisionalLoad(
489 blink::WebLocalFrame* frame,
490 const blink::WebHistoryItem& item,
491 blink::WebHistoryCommitType commit_type) {
492 state_.origin = FrameOrigin(frame);
493 server_->SetClientProperty(kPropertyFrameOrigin,
494 FrameOriginToClientProperty(frame));
495
496 // TODO(erg): We need to pass way more information from here through to the
497 // other side. See FrameHostMsg_DidCommitProvisionalLoad_Params. It is a grab
498 // bag of everything and it looks like a combination of
499 // NavigatorImpl::DidNavigate and
500 // NavigationControllerImpl::RendererDidNavigate use everything passed
501 // through.
502 server_->DidCommitProvisionalLoad();
503
504 if (!navigation_start_time_.is_null()) {
505 frame->dataSource()->setNavigationStartTime(
506 navigation_start_time_.ToInternalValue() /
507 static_cast<double>(base::Time::kMicrosecondsPerSecond));
508 navigation_start_time_ = base::TimeTicks();
509 }
510 }
511
512 void HTMLFrame::didReceiveTitle(blink::WebLocalFrame* frame,
513 const blink::WebString& title,
514 blink::WebTextDirection direction) {
515 // TODO(beng): handle |direction|.
516 mojo::String formatted;
517 if (!title.isNull()) {
518 formatted =
519 mojo::String::From(base::string16(title).substr(0, kMaxTitleChars));
520 }
521 server_->TitleChanged(formatted);
522 }
523
524 void HTMLFrame::reportFindInFrameMatchCount(int identifier,
525 int count,
526 bool finalUpdate) {
527 server_->OnFindInFrameCountUpdated(identifier, count, finalUpdate);
528 }
529
530 void HTMLFrame::reportFindInPageSelection(int identifier,
531 int activeMatchOrdinal,
532 const blink::WebRect& selection) {
533 server_->OnFindInPageSelectionUpdated(identifier, activeMatchOrdinal);
534 }
535
536 bool HTMLFrame::shouldSearchSingleFrame() {
537 return true;
538 }
539
540 void HTMLFrame::Bind(
541 web_view::mojom::FramePtr frame,
542 mojo::InterfaceRequest<web_view::mojom::FrameClient> frame_client_request) {
543 DCHECK(IsLocal());
544 server_ = std::move(frame);
545 server_.set_connection_error_handler(
546 base::Bind(&HTMLFrame::Close, base::Unretained(this)));
547 frame_client_binding_.reset(new mojo::Binding<web_view::mojom::FrameClient>(
548 this, std::move(frame_client_request)));
549 }
550
551 void HTMLFrame::SetValueFromClientProperty(const std::string& name,
552 mojo::Array<uint8_t> new_data) {
553 if (IsLocal())
554 return;
555
556 // Only the name and origin dynamically change.
557 if (name == kPropertyFrameOrigin) {
558 state_.origin = FrameOriginFromClientProperty(new_data);
559 web_frame_->toWebRemoteFrame()->setReplicatedOrigin(state_.origin);
560 } else if (name == kPropertyFrameName) {
561 state_.name = FrameNameFromClientProperty(new_data);
562 web_frame_->toWebRemoteFrame()->setReplicatedName(state_.name);
563 }
564 }
565
566 HTMLFrame* HTMLFrame::GetFirstAncestorWithDelegate() {
567 HTMLFrame* frame = this;
568 while (frame && !frame->delegate_)
569 frame = frame->parent_;
570 return frame;
571 }
572
573 mojo::Shell* HTMLFrame::GetShell() {
574 return GetFirstAncestorWithDelegate()->delegate_->GetShell();
575 }
576
577 web_view::mojom::Frame* HTMLFrame::GetServerFrame() {
578 // Prefer an ancestor with a server Frame.
579 for (HTMLFrame* frame = this; frame; frame = frame->parent_) {
580 if (frame->server_.get())
581 return frame->server_.get();
582 }
583
584 // We're a remote frame with no local frame ancestors. Use the server Frame
585 // from the local frame of the HTMLFrameTreeManager.
586 return frame_tree_manager_->local_frame_->server_.get();
587 }
588
589 void HTMLFrame::SetWindow(mus::Window* window) {
590 if (window_) {
591 window_->set_input_event_handler(nullptr);
592 window_->RemoveObserver(this);
593 }
594 window_ = window;
595 if (window_) {
596 window_->AddObserver(this);
597 window_->set_input_event_handler(this);
598 }
599 }
600
601 void HTMLFrame::CreateRootWebWidget() {
602 DCHECK(!html_widget_);
603 if (window_) {
604 HTMLWidgetRootLocal::CreateParams create_params(GetShell(), global_state(),
605 window_);
606 html_widget_.reset(
607 delegate_->GetHTMLFactory()->CreateHTMLWidgetRootLocal(&create_params));
608 } else {
609 html_widget_.reset(new HTMLWidgetRootRemote(global_state()));
610 }
611 }
612
613 void HTMLFrame::CreateLocalRootWebWidget(blink::WebLocalFrame* local_frame) {
614 DCHECK(!html_widget_);
615 DCHECK(IsLocal());
616 html_widget_.reset(new HTMLWidgetLocalRoot(GetShell(), global_state(),
617 window_, local_frame));
618 }
619
620 void HTMLFrame::UpdateFocus() {
621 blink::WebWidget* web_widget = GetWebWidget();
622 if (!web_widget || !window_)
623 return;
624 const bool is_focused = window_ && window_->HasFocus();
625 web_widget->setFocus(is_focused);
626 if (web_widget->isWebView())
627 static_cast<blink::WebView*>(web_widget)->setIsActive(is_focused);
628 }
629
630 void HTMLFrame::SwapToRemote() {
631 TRACE_EVENT0("html_viewer", "HTMLFrame::SwapToRemote");
632
633 DVLOG(2) << "HTMLFrame::SwapToRemote this=" << this << " id=" << id_;
634
635 DCHECK(IsLocal());
636
637 HTMLFrameDelegate* delegate = delegate_;
638 delegate_ = nullptr;
639
640 blink::WebRemoteFrame* remote_frame =
641 blink::WebRemoteFrame::create(state_.tree_scope, this);
642 remote_frame->initializeFromFrame(web_frame_->toWebLocalFrame());
643 // swap() ends up calling us back and we then close the frame, which deletes
644 // it.
645 web_frame_->swap(remote_frame);
646 if (owned_window_) {
647 surface_layer_ =
648 cc::SurfaceLayer::Create(cc_blink::WebLayerImpl::LayerSettings(),
649 base::Bind(&SatisfyCallback),
650 base::Bind(&RequireCallback));
651 surface_layer_->SetSurfaceId(cc::SurfaceId(owned_window_->window()->id()),
652 global_state()->device_pixel_ratio(),
653 owned_window_->window()->bounds().size());
654
655 web_layer_.reset(new cc_blink::WebLayerImpl(surface_layer_));
656 }
657 remote_frame->setRemoteWebLayer(web_layer_.get());
658 remote_frame->setReplicatedName(state_.name);
659 remote_frame->setReplicatedOrigin(state_.origin);
660 remote_frame->setReplicatedSandboxFlags(state_.sandbox_flags);
661
662 // Tell the frame that it is actually loading. This prevents its parent
663 // from prematurely dispatching load event.
664 remote_frame->didStartLoading();
665 pending_navigation_ = false;
666
667 web_frame_ = remote_frame;
668 SetWindow(nullptr);
669 server_.reset();
670 frame_client_binding_.reset();
671 if (delegate)
672 delegate->OnFrameSwappedToRemote();
673 }
674
675 void HTMLFrame::SwapToLocal(
676 HTMLFrameDelegate* delegate,
677 mus::Window* window,
678 const mojo::Map<mojo::String, mojo::Array<uint8_t>>& properties) {
679 TRACE_EVENT0("html_viewer", "HTMLFrame::SwapToLocal");
680 DVLOG(2) << "HTMLFrame::SwapToLocal this=" << this << " id=" << id_;
681 CHECK(!IsLocal());
682 // It doesn't make sense for the root to swap to local.
683 CHECK(parent_);
684 delegate_ = delegate;
685 SetWindow(window);
686 SetReplicatedFrameStateFromClientProperties(properties, &state_);
687 blink::WebLocalFrame* local_web_frame =
688 blink::WebLocalFrame::createProvisional(
689 this, web_frame_->toWebRemoteFrame(), state_.sandbox_flags,
690 // TODO(lazyboy): Figure out replicating WebFrameOwnerProperties.
691 blink::WebFrameOwnerProperties());
692 // The swap() ends up calling to frameDetached() and deleting the old.
693 web_frame_->swap(local_web_frame);
694 web_frame_ = local_web_frame;
695
696 web_layer_.reset();
697 }
698
699 void HTMLFrame::SwapDelegate(HTMLFrameDelegate* delegate) {
700 DCHECK(IsLocal());
701 HTMLFrameDelegate* old_delegate = delegate_;
702 delegate_ = delegate;
703 delegate->OnSwap(this, old_delegate);
704 }
705
706 blink::WebElement HTMLFrame::GetFocusedElement() {
707 if (!web_view())
708 return blink::WebElement();
709
710 HTMLFrame* frame = this;
711 while (frame) {
712 if (frame->web_view()) {
713 if (frame->web_view()->focusedFrame() == web_frame_) {
714 blink::WebDocument doc = web_frame_->document();
715 if (!doc.isNull())
716 return doc.focusedElement();
717 }
718 return blink::WebElement();
719 }
720 frame = frame->parent();
721 }
722
723 return blink::WebElement();
724 }
725
726 HTMLFrame* HTMLFrame::FindFrameWithWebFrame(blink::WebFrame* web_frame) {
727 if (web_frame_ == web_frame)
728 return this;
729 for (HTMLFrame* child_frame : children_) {
730 HTMLFrame* result = child_frame->FindFrameWithWebFrame(web_frame);
731 if (result)
732 return result;
733 }
734 return nullptr;
735 }
736
737 void HTMLFrame::FrameDetachedImpl(blink::WebFrame* web_frame) {
738 DCHECK_EQ(web_frame_, web_frame);
739
740 while (!children_.empty()) {
741 HTMLFrame* child = children_.front();
742 child->Close();
743 DCHECK(children_.empty() || children_.front() != child);
744 }
745
746 if (web_frame->parent())
747 web_frame->parent()->removeChild(web_frame);
748
749 delete this;
750 }
751
752 void HTMLFrame::OnWindowBoundsChanged(mus::Window* window,
753 const gfx::Rect& old_bounds,
754 const gfx::Rect& new_bounds) {
755 DCHECK_EQ(window, window_);
756 if (html_widget_)
757 html_widget_->OnWindowBoundsChanged(window);
758 }
759
760 void HTMLFrame::OnWindowDestroyed(mus::Window* window) {
761 DCHECK_EQ(window, window_);
762 window_->RemoveObserver(this);
763 window_ = nullptr;
764 Close();
765 }
766
767 void HTMLFrame::OnWindowFocusChanged(mus::Window* gained_focus,
768 mus::Window* lost_focus) {
769 UpdateFocus();
770 }
771
772 void HTMLFrame::OnWindowInputEvent(mus::Window* window,
773 mus::mojom::EventPtr event,
774 scoped_ptr<base::Closure>* ack_callback) {
775 if (event->pointer_data && event->pointer_data->location) {
776 // Blink expects coordintes to be in DIPs.
777 event->pointer_data->location->x /= global_state()->device_pixel_ratio();
778 event->pointer_data->location->y /= global_state()->device_pixel_ratio();
779 event->pointer_data->location->screen_x /=
780 global_state()->device_pixel_ratio();
781 event->pointer_data->location->screen_y /=
782 global_state()->device_pixel_ratio();
783 }
784
785 blink::WebWidget* web_widget = GetWebWidget();
786
787 if (!touch_handler_ && web_widget)
788 touch_handler_.reset(new TouchHandler(web_widget));
789
790 if (touch_handler_ &&
791 (event->action == mus::mojom::EventType::POINTER_DOWN ||
792 event->action == mus::mojom::EventType::POINTER_UP ||
793 event->action == mus::mojom::EventType::POINTER_CANCEL ||
794 event->action == mus::mojom::EventType::POINTER_MOVE) &&
795 event->pointer_data &&
796 event->pointer_data->kind == mus::mojom::PointerKind::TOUCH) {
797 touch_handler_->OnTouchEvent(*event);
798 return;
799 }
800
801 if (!web_widget)
802 return;
803
804 scoped_ptr<blink::WebInputEvent> web_event =
805 event.To<scoped_ptr<blink::WebInputEvent>>();
806 if (web_event)
807 web_widget->handleInputEvent(*web_event);
808 }
809
810 void HTMLFrame::OnConnect(
811 web_view::mojom::FramePtr frame,
812 uint32_t change_id,
813 uint32_t window_id,
814 web_view::mojom::WindowConnectType window_connect_type,
815 mojo::Array<web_view::mojom::FrameDataPtr> frame_data,
816 int64_t navigation_start_time_ticks,
817 const OnConnectCallback& callback) {
818 // This is called if this frame is created by way of OnCreatedFrame().
819 callback.Run();
820 }
821
822 void HTMLFrame::OnFrameAdded(uint32_t change_id,
823 web_view::mojom::FrameDataPtr frame_data) {
824 frame_tree_manager_->ProcessOnFrameAdded(this, change_id,
825 std::move(frame_data));
826 }
827
828 void HTMLFrame::OnFrameRemoved(uint32_t change_id, uint32_t frame_id) {
829 frame_tree_manager_->ProcessOnFrameRemoved(this, change_id, frame_id);
830 }
831
832 void HTMLFrame::OnFrameClientPropertyChanged(uint32_t frame_id,
833 const mojo::String& name,
834 mojo::Array<uint8_t> new_value) {
835 frame_tree_manager_->ProcessOnFrameClientPropertyChanged(
836 this, frame_id, name, std::move(new_value));
837 }
838
839 void HTMLFrame::OnPostMessageEvent(uint32_t source_frame_id,
840 uint32_t target_frame_id,
841 HTMLMessageEventPtr serialized_event) {
842 NOTIMPLEMENTED(); // For message ports.
843
844 HTMLFrame* target = frame_tree_manager_->root_->FindFrame(target_frame_id);
845 HTMLFrame* source = frame_tree_manager_->root_->FindFrame(source_frame_id);
846 if (!target || !source) {
847 DVLOG(1) << "Invalid source or target for PostMessage";
848 return;
849 }
850
851 if (!target->IsLocal()) {
852 DVLOG(1) << "Target for PostMessage is not lot local";
853 return;
854 }
855
856 blink::WebLocalFrame* target_web_frame =
857 target->web_frame_->toWebLocalFrame();
858
859 blink::WebSerializedScriptValue serialized_script_value;
860 serialized_script_value = blink::WebSerializedScriptValue::fromString(
861 serialized_event->data.To<blink::WebString>());
862
863 // We must pass in the target_origin to do the security check on this side,
864 // since it may have changed since the original postMessage call was made.
865 blink::WebSecurityOrigin target_origin;
866 if (!serialized_event->target_origin.is_null()) {
867 target_origin = blink::WebSecurityOrigin::createFromString(
868 serialized_event->target_origin.To<blink::WebString>());
869 }
870
871 // TODO(esprehn): Shouldn't this also fill in channels like RenderFrameImpl?
872 blink::WebMessagePortChannelArray channels;
873 blink::WebDOMMessageEvent msg_event(serialized_script_value,
874 serialized_event->source_origin.To<blink::WebString>(),
875 source->web_frame_, target_web_frame->document(), channels);
876
877 target_web_frame->dispatchMessageEventWithOriginCheck(target_origin,
878 msg_event);
879 }
880
881 void HTMLFrame::OnWillNavigate(const mojo::String& origin,
882 const OnWillNavigateCallback& callback) {
883 bool should_swap = true;
884
885 if (this == frame_tree_manager_->local_frame_) {
886 HTMLFrame* new_local_frame = frame_tree_manager_->FindNewLocalFrame();
887 if (!new_local_frame) {
888 // All local frames are descendants of |this|. In this case, the whole
889 // frame tree in the current process is going to be deleted very soon. We
890 // don't have to swap.
891 should_swap = false;
892 } else {
893 frame_tree_manager_->local_frame_ = new_local_frame;
894 }
895 }
896
897 DVLOG(2) << "HTMLFrame::OnWillNavigate this=" << this << " id=" << id_
898 << " local=" << IsLocal() << " should_swap=" << should_swap;
899 callback.Run();
900 if (should_swap) {
901 SwapToRemote();
902 const blink::WebSecurityOrigin security_origin(
903 blink::WebSecurityOrigin::createFromString(
904 blink::WebString::fromUTF8(origin)));
905 web_frame_->toWebRemoteFrame()->setReplicatedOrigin(security_origin);
906 }
907 }
908
909 void HTMLFrame::OnFrameLoadingStateChanged(uint32_t frame_id, bool loading) {
910 HTMLFrame* frame = frame_tree_manager_->root_->FindFrame(frame_id);
911 // TODO(yzshen): (Apply to this method and the one below.) Is it possible that
912 // at this point the frame is already hosting a different document?
913 if (frame && !frame->IsLocal()) {
914 if (loading)
915 frame->web_frame_->toWebRemoteFrame()->didStartLoading();
916 else
917 frame->web_frame_->toWebRemoteFrame()->didStopLoading();
918 }
919 }
920
921 void HTMLFrame::OnDispatchFrameLoadEvent(uint32_t frame_id) {
922 HTMLFrame* frame = frame_tree_manager_->root_->FindFrame(frame_id);
923 if (frame && !frame->IsLocal())
924 frame->web_frame_->toWebRemoteFrame()->DispatchLoadEventForFrameOwner();
925 }
926
927 void HTMLFrame::Find(int32_t request_id,
928 const mojo::String& search_text,
929 web_view::mojom::FindOptionsPtr options,
930 bool wrap_within_frame,
931 const FindCallback& callback) {
932 blink::WebRect selection_rect;
933 bool result = web_frame_->toWebLocalFrame()->find(
934 request_id, search_text.To<blink::WebString>(),
935 options.To<blink::WebFindOptions>(), wrap_within_frame, &selection_rect);
936
937 if (!result) {
938 // don't leave text selected as you move to the next frame.
939 web_frame_->executeCommand(blink::WebString::fromUTF8("Unselect"),
940 GetFocusedElement());
941 }
942
943 callback.Run(result);
944 }
945
946 void HTMLFrame::StopFinding(bool clear_selection) {
947 // TODO(erg): |clear_selection| isn't correct; this should be a state enum
948 // that lets us STOP_FIND_ACTION_ACTIVATE_SELECTION, too.
949 if (clear_selection) {
950 blink::WebElement focused_element = GetFocusedElement();
951 if (!focused_element.isNull()) {
952 web_frame_->executeCommand(blink::WebString::fromUTF8("Unselect"),
953 focused_element);
954 }
955 }
956
957 web_frame_->toWebLocalFrame()->stopFinding(clear_selection);
958 }
959
960 void HTMLFrame::HighlightFindResults(int32_t request_id,
961 const mojo::String& search_text,
962 web_view::mojom::FindOptionsPtr options,
963 bool reset) {
964 web_frame_->toWebLocalFrame()->scopeStringMatches(
965 request_id, search_text.To<blink::WebString>(),
966 options.To<blink::WebFindOptions>(), reset);
967 }
968
969 void HTMLFrame::StopHighlightingFindResults() {
970 web_frame_->toWebLocalFrame()->resetMatchCount();
971 web_frame_->toWebLocalFrame()->cancelPendingScopingEffort();
972 }
973
974 void HTMLFrame::frameDetached(blink::WebRemoteFrameClient::DetachType type) {
975 if (type == blink::WebRemoteFrameClient::DetachType::Swap) {
976 web_frame_->close();
977 return;
978 }
979
980 DCHECK(type == blink::WebRemoteFrameClient::DetachType::Remove);
981 FrameDetachedImpl(web_frame_);
982 }
983
984 void HTMLFrame::postMessageEvent(blink::WebLocalFrame* source_web_frame,
985 blink::WebRemoteFrame* target_web_frame,
986 blink::WebSecurityOrigin target_origin,
987 blink::WebDOMMessageEvent web_event) {
988 NOTIMPLEMENTED(); // message_ports aren't implemented yet.
989
990 HTMLFrame* source_frame =
991 frame_tree_manager_->root_->FindFrameWithWebFrame(source_web_frame);
992 DCHECK(source_frame);
993 HTMLFrame* target_frame =
994 frame_tree_manager_->root_->FindFrameWithWebFrame(target_web_frame);
995 DCHECK(target_frame);
996
997 HTMLMessageEventPtr event(HTMLMessageEvent::New());
998 event->data = mojo::Array<uint8_t>::From(web_event.data().toString());
999 event->source_origin = mojo::String::From(web_event.origin());
1000 if (!target_origin.isNull())
1001 event->target_origin = mojo::String::From(target_origin.toString());
1002
1003 source_frame->server_->PostMessageEventToFrame(target_frame->id_,
1004 std::move(event));
1005 }
1006
1007 void HTMLFrame::initializeChildFrame(const blink::WebRect& frame_rect,
1008 float scale_factor) {
1009 // NOTE: |scale_factor| is always 1.
1010 const gfx::Rect rect_in_dip(frame_rect.x, frame_rect.y, frame_rect.width,
1011 frame_rect.height);
1012 const gfx::Rect rect_in_pixels(gfx::ConvertRectToPixel(
1013 global_state()->device_pixel_ratio(), rect_in_dip));
1014 window_->SetBounds(rect_in_pixels);
1015 }
1016
1017 void HTMLFrame::navigate(const blink::WebURLRequest& request,
1018 bool should_replace_current_entry) {
1019 // TODO: support |should_replace_current_entry|.
1020 NOTIMPLEMENTED(); // for |should_replace_current_entry
1021 mojo::URLRequestPtr url_request = mojo::URLRequest::From(request);
1022 GetServerFrame()->RequestNavigate(
1023 web_view::mojom::NavigationTargetType::EXISTING_FRAME, id_,
1024 std::move(url_request));
1025 }
1026
1027 void HTMLFrame::reload(bool ignore_cache, bool is_client_redirect) {
1028 NOTIMPLEMENTED();
1029 }
1030
1031 void HTMLFrame::frameRectsChanged(const blink::WebRect& frame_rect) {
1032 // Only the owner of window can update its size.
1033 if (!owned_window_)
1034 return;
1035
1036 const gfx::Rect rect_in_dip(frame_rect.x, frame_rect.y, frame_rect.width,
1037 frame_rect.height);
1038 const gfx::Rect rect_in_pixels(gfx::ConvertRectToPixel(
1039 global_state()->device_pixel_ratio(), rect_in_dip));
1040 owned_window_->window()->SetBounds(rect_in_pixels);
1041
1042 if (!surface_layer_)
1043 return;
1044
1045 surface_layer_->SetSurfaceId(cc::SurfaceId(owned_window_->window()->id()),
1046 global_state()->device_pixel_ratio(),
1047 owned_window_->window()->bounds().size());
1048 }
1049
1050 } // namespace mojo
OLDNEW
« no previous file with comments | « components/html_viewer/html_frame.h ('k') | components/html_viewer/html_frame_apptest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698