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

Side by Side Diff: extensions/browser/guest_view/web_view/web_view_guest.cc

Issue 1392343002: Reduce the public method footprint of GuestViewBase and derived types. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/browser/guest_view/web_view/web_view_guest.h" 5 #include "extensions/browser/guest_view/web_view/web_view_guest.h"
6 6
7 #include "base/message_loop/message_loop.h" 7 #include "base/message_loop/message_loop.h"
8 #include "base/strings/stringprintf.h" 8 #include "base/strings/stringprintf.h"
9 #include "base/strings/utf_string_conversions.h" 9 #include "base/strings/utf_string_conversions.h"
10 #include "components/browsing_data/storage_partition_http_cache_data_remover.h" 10 #include "components/browsing_data/storage_partition_http_cache_data_remover.h"
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 return zoom_factor; 194 return zoom_factor;
195 } 195 }
196 196
197 using WebViewKey = std::pair<int, int>; 197 using WebViewKey = std::pair<int, int>;
198 using WebViewKeyToIDMap = std::map<WebViewKey, int>; 198 using WebViewKeyToIDMap = std::map<WebViewKey, int>;
199 static base::LazyInstance<WebViewKeyToIDMap> web_view_key_to_id_map = 199 static base::LazyInstance<WebViewKeyToIDMap> web_view_key_to_id_map =
200 LAZY_INSTANCE_INITIALIZER; 200 LAZY_INSTANCE_INITIALIZER;
201 201
202 } // namespace 202 } // namespace
203 203
204 WebViewGuest::WebViewGuest(WebContents* owner_web_contents)
205 : GuestView<WebViewGuest>(owner_web_contents),
206 rules_registry_id_(RulesRegistryService::kInvalidRulesRegistryID),
207 find_helper_(this),
208 is_overriding_user_agent_(false),
209 allow_transparency_(false),
210 javascript_dialog_helper_(this),
211 allow_scaling_(false),
212 is_guest_fullscreen_(false),
213 is_embedder_fullscreen_(false),
214 last_fullscreen_permission_was_allowed_by_embedder_(false),
215 pending_zoom_factor_(0.0),
216 weak_ptr_factory_(this) {
217 web_view_guest_delegate_.reset(
218 ExtensionsAPIClient::Get()->CreateWebViewGuestDelegate(this));
219 }
220
221 WebViewGuest::~WebViewGuest() {}
222
204 // static 223 // static
205 void WebViewGuest::CleanUp(content::BrowserContext* browser_context, 224 void WebViewGuest::CleanUp(content::BrowserContext* browser_context,
206 int embedder_process_id, 225 int embedder_process_id,
207 int view_instance_id) { 226 int view_instance_id) {
208 GuestViewBase::CleanUp(browser_context, embedder_process_id, 227 GuestViewBase::CleanUp(browser_context, embedder_process_id,
209 view_instance_id); 228 view_instance_id);
210 229
211 // Clean up rules registries for the WebView. 230 // Clean up rules registries for the WebView.
212 WebViewKey key(embedder_process_id, view_instance_id); 231 WebViewKey key(embedder_process_id, view_instance_id);
213 auto it = web_view_key_to_id_map.Get().find(key); 232 auto it = web_view_key_to_id_map.Get().find(key);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 return it->second; 315 return it->second;
297 316
298 auto rph = RenderProcessHost::FromID(embedder_process_id); 317 auto rph = RenderProcessHost::FromID(embedder_process_id);
299 int rules_registry_id = 318 int rules_registry_id =
300 RulesRegistryService::Get(rph->GetBrowserContext())-> 319 RulesRegistryService::Get(rph->GetBrowserContext())->
301 GetNextRulesRegistryID(); 320 GetNextRulesRegistryID();
302 web_view_key_to_id_map.Get()[key] = rules_registry_id; 321 web_view_key_to_id_map.Get()[key] = rules_registry_id;
303 return rules_registry_id; 322 return rules_registry_id;
304 } 323 }
305 324
306 bool WebViewGuest::CanRunInDetachedState() const { 325 double WebViewGuest::GetZoom() const {
307 return true; 326 double zoom_level =
327 ZoomController::FromWebContents(web_contents())->GetZoomLevel();
328 return ConvertZoomLevelToZoomFactor(zoom_level);
308 } 329 }
309 330
310 void WebViewGuest::CreateWebContents( 331 ZoomController::ZoomMode WebViewGuest::GetZoomMode() {
311 const base::DictionaryValue& create_params, 332 return ZoomController::FromWebContents(web_contents())->zoom_mode();
312 const WebContentsCreatedCallback& callback) { 333 }
313 RenderProcessHost* owner_render_process_host = 334
314 owner_web_contents()->GetRenderProcessHost(); 335 void WebViewGuest::NavigateGuest(const std::string& src,
315 std::string storage_partition_id; 336 bool force_navigation) {
316 bool persist_storage = false; 337 if (src.empty())
317 ParsePartitionParam(create_params, &storage_partition_id, &persist_storage); 338 return;
318 // Validate that the partition id coming from the renderer is valid UTF-8, 339
319 // since we depend on this in other parts of the code, such as FilePath 340 GURL url = ResolveURL(src);
320 // creation. If the validation fails, treat it as a bad message and kill the 341
321 // renderer process. 342 // We wait for all the content scripts to load and then navigate the guest
322 if (!base::IsStringUTF8(storage_partition_id)) { 343 // if the navigation is embedder-initiated. For browser-initiated navigations,
323 content::RecordAction( 344 // content scripts will be ready.
324 base::UserMetricsAction("BadMessageTerminate_BPGM")); 345 if (force_navigation) {
325 owner_render_process_host->Shutdown(content::RESULT_CODE_KILLED_BAD_MESSAGE, 346 SignalWhenReady(base::Bind(
326 false); 347 &WebViewGuest::LoadURLWithParams, weak_ptr_factory_.GetWeakPtr(), url,
327 callback.Run(nullptr); 348 content::Referrer(), ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
349 GlobalRequestID(), force_navigation));
328 return; 350 return;
329 } 351 }
330 std::string url_encoded_partition = net::EscapeQueryParamValue( 352 LoadURLWithParams(url, content::Referrer(), ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
331 storage_partition_id, false); 353 GlobalRequestID(), force_navigation);
332 std::string partition_domain = GetOwnerSiteURL().host();
333 GURL guest_site(base::StringPrintf("%s://%s/%s?%s",
334 content::kGuestScheme,
335 partition_domain.c_str(),
336 persist_storage ? "persist" : "",
337 url_encoded_partition.c_str()));
338
339 // If we already have a webview tag in the same app using the same storage
340 // partition, we should use the same SiteInstance so the existing tag and
341 // the new tag can script each other.
342 auto guest_view_manager = GuestViewManager::FromBrowserContext(
343 owner_render_process_host->GetBrowserContext());
344 content::SiteInstance* guest_site_instance =
345 guest_view_manager->GetGuestSiteInstance(guest_site);
346 if (!guest_site_instance) {
347 // Create the SiteInstance in a new BrowsingInstance, which will ensure
348 // that webview tags are also not allowed to send messages across
349 // different partitions.
350 guest_site_instance = content::SiteInstance::CreateForURL(
351 owner_render_process_host->GetBrowserContext(), guest_site);
352 }
353 WebContents::CreateParams params(
354 owner_render_process_host->GetBrowserContext(),
355 guest_site_instance);
356 params.guest_delegate = this;
357 callback.Run(WebContents::Create(params));
358 } 354 }
359 355
360 void WebViewGuest::DidAttachToEmbedder() { 356 void WebViewGuest::ShowContextMenu(
361 ApplyAttributes(*attach_params()); 357 int request_id,
358 const WebViewGuestDelegate::MenuItemVector* items) {
359 if (web_view_guest_delegate_)
360 web_view_guest_delegate_->OnShowContextMenu(request_id, items);
362 } 361 }
363 362
364 void WebViewGuest::DidDropLink(const GURL& url) { 363 void WebViewGuest::SetName(const std::string& name) {
365 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue()); 364 if (name_ == name)
366 args->SetString(guest_view::kUrl, url.spec()); 365 return;
367 DispatchEventToView( 366 name_ = name;
368 new GuestViewEvent(webview::kEventDropLink, args.Pass())); 367
368 Send(new ExtensionMsg_SetFrameName(routing_id(), name_));
369 } 369 }
370 370
371 void WebViewGuest::DidInitialize(const base::DictionaryValue& create_params) { 371 void WebViewGuest::SetZoom(double zoom_factor) {
372 script_executor_.reset( 372 auto zoom_controller = ZoomController::FromWebContents(web_contents());
373 new ScriptExecutor(web_contents(), &script_observers_)); 373 DCHECK(zoom_controller);
374 374 double zoom_level = content::ZoomFactorToZoomLevel(zoom_factor);
375 notification_registrar_.Add(this, 375 zoom_controller->SetZoomLevel(zoom_level);
376 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
377 content::Source<WebContents>(web_contents()));
378
379 notification_registrar_.Add(this,
380 content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
381 content::Source<WebContents>(web_contents()));
382
383 if (web_view_guest_delegate_)
384 web_view_guest_delegate_->OnDidInitialize();
385 ExtensionsAPIClient::Get()->AttachWebContentsHelpers(web_contents());
386 web_view_permission_helper_.reset(new WebViewPermissionHelper(this));
387
388 rules_registry_id_ = GetOrGenerateRulesRegistryID(
389 owner_web_contents()->GetRenderProcessHost()->GetID(),
390 view_instance_id());
391
392 // We must install the mapping from guests to WebViews prior to resuming
393 // suspended resource loads so that the WebRequest API will catch resource
394 // requests.
395 PushWebViewStateToIOThread();
396
397 ApplyAttributes(create_params);
398 } 376 }
399 377
400 void WebViewGuest::ClearDataInternal(base::Time remove_since, 378 void WebViewGuest::SetZoomMode(ZoomController::ZoomMode zoom_mode) {
401 uint32 removal_mask, 379 ZoomController::FromWebContents(web_contents())->SetZoomMode(zoom_mode);
402 const base::Closure& callback) {
403 uint32 storage_partition_removal_mask =
404 GetStoragePartitionRemovalMask(removal_mask);
405 if (!storage_partition_removal_mask) {
406 callback.Run();
407 return;
408 }
409 content::StoragePartition* partition =
410 content::BrowserContext::GetStoragePartition(
411 web_contents()->GetBrowserContext(),
412 web_contents()->GetSiteInstance());
413 partition->ClearData(
414 storage_partition_removal_mask,
415 content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, GURL(),
416 content::StoragePartition::OriginMatcherFunction(), remove_since,
417 base::Time::Now(), callback);
418 } 380 }
419 381
420 void WebViewGuest::GuestViewDidStopLoading() { 382 void WebViewGuest::SetAllowScaling(bool allow) {
421 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue()); 383 allow_scaling_ = allow;
422 DispatchEventToView(
423 new GuestViewEvent(webview::kEventLoadStop, args.Pass()));
424 } 384 }
425 385
426 void WebViewGuest::EmbedderFullscreenToggled(bool entered_fullscreen) { 386 void WebViewGuest::SetAllowTransparency(bool allow) {
427 is_embedder_fullscreen_ = entered_fullscreen; 387 if (allow_transparency_ == allow)
428 // If the embedder has got out of fullscreen, we get out of fullscreen 388 return;
429 // mode as well.
430 if (!entered_fullscreen)
431 SetFullscreenState(false);
432 }
433 389
434 const char* WebViewGuest::GetAPINamespace() const { 390 allow_transparency_ = allow;
435 return webview::kAPINamespace; 391 if (!web_contents()->GetRenderViewHost()->GetView())
436 } 392 return;
437 393
438 int WebViewGuest::GetTaskPrefix() const {
439 return IDS_EXTENSION_TASK_MANAGER_WEBVIEW_TAG_PREFIX;
440 }
441
442 void WebViewGuest::GuestDestroyed() {
443 RemoveWebViewStateFromIOThread(web_contents());
444 }
445
446 void WebViewGuest::GuestReady() {
447 // The guest RenderView should always live in an isolated guest process.
448 CHECK(web_contents()->GetRenderProcessHost()->IsForGuestsOnly());
449 Send(new ExtensionMsg_SetFrameName(web_contents()->GetRoutingID(), name_));
450
451 // We don't want to accidentally set the opacity of an interstitial page.
452 // WebContents::GetRenderWidgetHostView will return the RWHV of an
453 // interstitial page if one is showing at this time. We only want opacity
454 // to apply to web pages.
455 if (allow_transparency_) { 394 if (allow_transparency_) {
456 web_contents()->GetRenderViewHost()->GetView()->SetBackgroundColor( 395 web_contents()->GetRenderViewHost()->GetView()->SetBackgroundColor(
457 SK_ColorTRANSPARENT); 396 SK_ColorTRANSPARENT);
458 } else { 397 } else {
459 web_contents() 398 web_contents()
460 ->GetRenderViewHost() 399 ->GetRenderViewHost()
461 ->GetView() 400 ->GetView()
462 ->SetBackgroundColorToDefault(); 401 ->SetBackgroundColorToDefault();
463 } 402 }
464 } 403 }
465 404
466 void WebViewGuest::GuestSizeChangedDueToAutoSize(const gfx::Size& old_size, 405 bool WebViewGuest::LoadDataWithBaseURL(const std::string& data_url,
467 const gfx::Size& new_size) { 406 const std::string& base_url,
468 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue()); 407 const std::string& virtual_url,
469 args->SetInteger(webview::kOldHeight, old_size.height()); 408 std::string* error) {
470 args->SetInteger(webview::kOldWidth, old_size.width()); 409 // Make GURLs from URLs.
471 args->SetInteger(webview::kNewHeight, new_size.height()); 410 const GURL data_gurl = GURL(data_url);
472 args->SetInteger(webview::kNewWidth, new_size.width()); 411 const GURL base_gurl = GURL(base_url);
473 DispatchEventToView( 412 const GURL virtual_gurl = GURL(virtual_url);
474 new GuestViewEvent(webview::kEventSizeChanged, args.Pass()));
475 }
476 413
477 bool WebViewGuest::IsAutoSizeSupported() const { 414 // Check that the provided URLs are valid.
415 // |data_url| must be a valid data URL.
416 if (!data_gurl.is_valid() || !data_gurl.SchemeIs(url::kDataScheme)) {
417 base::SStringPrintf(error, webview::kAPILoadDataInvalidDataURL,
418 data_url.c_str());
419 return false;
420 }
421 // |base_url| must be a valid URL.
422 if (!base_gurl.is_valid()) {
423 base::SStringPrintf(error, webview::kAPILoadDataInvalidBaseURL,
424 base_url.c_str());
425 return false;
426 }
427 // |virtual_url| must be a valid URL.
428 if (!virtual_gurl.is_valid()) {
429 base::SStringPrintf(error, webview::kAPILoadDataInvalidVirtualURL,
430 virtual_url.c_str());
431 return false;
432 }
433
434 // Set up the parameters to load |data_url| with the specified |base_url|.
435 content::NavigationController::LoadURLParams load_params(data_gurl);
436 load_params.load_type = content::NavigationController::LOAD_TYPE_DATA;
437 load_params.base_url_for_data_url = base_gurl;
438 load_params.virtual_url_for_data_url = virtual_gurl;
439 load_params.override_user_agent =
440 content::NavigationController::UA_OVERRIDE_INHERIT;
441
442 // Navigate to the data URL.
443 GuestViewBase::LoadURLWithParams(load_params);
444
478 return true; 445 return true;
479 } 446 }
480 447
481 void WebViewGuest::GuestZoomChanged(double old_zoom_level,
482 double new_zoom_level) {
483 // Dispatch the zoomchange event.
484 double old_zoom_factor = ConvertZoomLevelToZoomFactor(old_zoom_level);
485 double new_zoom_factor = ConvertZoomLevelToZoomFactor(new_zoom_level);
486 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
487 args->SetDouble(webview::kOldZoomFactor, old_zoom_factor);
488 args->SetDouble(webview::kNewZoomFactor, new_zoom_factor);
489 DispatchEventToView(
490 new GuestViewEvent(webview::kEventZoomChange, args.Pass()));
491 }
492
493 void WebViewGuest::WillDestroy() {
494 if (!attached() && GetOpener())
495 GetOpener()->pending_new_windows_.erase(this);
496 }
497
498 bool WebViewGuest::AddMessageToConsole(WebContents* source,
499 int32 level,
500 const base::string16& message,
501 int32 line_no,
502 const base::string16& source_id) {
503 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
504 // Log levels are from base/logging.h: LogSeverity.
505 args->SetInteger(webview::kLevel, level);
506 args->SetString(webview::kMessage, message);
507 args->SetInteger(webview::kLine, line_no);
508 args->SetString(webview::kSourceId, source_id);
509 DispatchEventToView(
510 new GuestViewEvent(webview::kEventConsoleMessage, args.Pass()));
511 return true;
512 }
513
514 void WebViewGuest::CloseContents(WebContents* source) {
515 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
516 DispatchEventToView(
517 new GuestViewEvent(webview::kEventClose, args.Pass()));
518 }
519
520 void WebViewGuest::FindReply(WebContents* source,
521 int request_id,
522 int number_of_matches,
523 const gfx::Rect& selection_rect,
524 int active_match_ordinal,
525 bool final_update) {
526 GuestViewBase::FindReply(source, request_id, number_of_matches,
527 selection_rect, active_match_ordinal, final_update);
528 find_helper_.FindReply(request_id, number_of_matches, selection_rect,
529 active_match_ordinal, final_update);
530 }
531
532 double WebViewGuest::GetZoom() const {
533 double zoom_level =
534 ZoomController::FromWebContents(web_contents())->GetZoomLevel();
535 return ConvertZoomLevelToZoomFactor(zoom_level);
536 }
537
538 ZoomController::ZoomMode WebViewGuest::GetZoomMode() {
539 return ZoomController::FromWebContents(web_contents())->zoom_mode();
540 }
541
542 bool WebViewGuest::HandleContextMenu(
543 const content::ContextMenuParams& params) {
544 if (!web_view_guest_delegate_)
545 return false;
546 return web_view_guest_delegate_->HandleContextMenu(params);
547 }
548
549 void WebViewGuest::HandleKeyboardEvent(
550 WebContents* source,
551 const content::NativeWebKeyboardEvent& event) {
552 if (HandleKeyboardShortcuts(event))
553 return;
554
555 GuestViewBase::HandleKeyboardEvent(source, event);
556 }
557
558 bool WebViewGuest::PreHandleGestureEvent(WebContents* source,
559 const blink::WebGestureEvent& event) {
560 return !allow_scaling_ && GuestViewBase::PreHandleGestureEvent(source, event);
561 }
562
563 void WebViewGuest::LoadProgressChanged(WebContents* source, double progress) {
564 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
565 args->SetString(guest_view::kUrl, web_contents()->GetURL().spec());
566 args->SetDouble(webview::kProgress, progress);
567 DispatchEventToView(
568 new GuestViewEvent(webview::kEventLoadProgress, args.Pass()));
569 }
570
571 void WebViewGuest::LoadAbort(bool is_top_level,
572 const GURL& url,
573 int error_code,
574 const std::string& error_type) {
575 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
576 args->SetBoolean(guest_view::kIsTopLevel, is_top_level);
577 args->SetString(guest_view::kUrl, url.possibly_invalid_spec());
578 args->SetInteger(guest_view::kCode, error_code);
579 args->SetString(guest_view::kReason, error_type);
580 DispatchEventToView(
581 new GuestViewEvent(webview::kEventLoadAbort, args.Pass()));
582 }
583
584 void WebViewGuest::SetContextMenuPosition(const gfx::Point& position) {
585 if (web_view_guest_delegate_)
586 web_view_guest_delegate_->SetContextMenuPosition(position);
587 }
588
589 void WebViewGuest::CreateNewGuestWebViewWindow(
590 const content::OpenURLParams& params) {
591 GuestViewManager* guest_manager =
592 GuestViewManager::FromBrowserContext(browser_context());
593 // Set the attach params to use the same partition as the opener.
594 // We pull the partition information from the site's URL, which is of the
595 // form guest://site/{persist}?{partition_name}.
596 const GURL& site_url = web_contents()->GetSiteInstance()->GetSiteURL();
597 const std::string storage_partition_id =
598 GetStoragePartitionIdFromSiteURL(site_url);
599 base::DictionaryValue create_params;
600 create_params.SetString(webview::kStoragePartitionId, storage_partition_id);
601
602 guest_manager->CreateGuest(WebViewGuest::Type,
603 embedder_web_contents(),
604 create_params,
605 base::Bind(&WebViewGuest::NewGuestWebViewCallback,
606 weak_ptr_factory_.GetWeakPtr(),
607 params));
608 }
609
610 void WebViewGuest::NewGuestWebViewCallback(const content::OpenURLParams& params,
611 WebContents* guest_web_contents) {
612 WebViewGuest* new_guest = WebViewGuest::FromWebContents(guest_web_contents);
613 new_guest->SetOpener(this);
614
615 // Take ownership of |new_guest|.
616 pending_new_windows_.insert(
617 std::make_pair(new_guest, NewWindowInfo(params.url, std::string())));
618
619 // Request permission to show the new window.
620 RequestNewWindowPermission(params.disposition,
621 gfx::Rect(),
622 params.user_gesture,
623 new_guest->web_contents());
624 }
625
626 // TODO(fsamuel): Find a reliable way to test the 'responsive' and
627 // 'unresponsive' events.
628 void WebViewGuest::RendererResponsive(WebContents* source) {
629 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
630 args->SetInteger(webview::kProcessId,
631 web_contents()->GetRenderProcessHost()->GetID());
632 DispatchEventToView(
633 new GuestViewEvent(webview::kEventResponsive, args.Pass()));
634 }
635
636 void WebViewGuest::RendererUnresponsive(WebContents* source) {
637 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
638 args->SetInteger(webview::kProcessId,
639 web_contents()->GetRenderProcessHost()->GetID());
640 DispatchEventToView(
641 new GuestViewEvent(webview::kEventUnresponsive, args.Pass()));
642 }
643
644 void WebViewGuest::Observe(int type,
645 const content::NotificationSource& source,
646 const content::NotificationDetails& details) {
647 switch (type) {
648 case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: {
649 DCHECK_EQ(content::Source<WebContents>(source).ptr(), web_contents());
650 if (content::Source<WebContents>(source).ptr() == web_contents())
651 LoadHandlerCalled();
652 break;
653 }
654 case content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: {
655 DCHECK_EQ(content::Source<WebContents>(source).ptr(), web_contents());
656 content::ResourceRedirectDetails* resource_redirect_details =
657 content::Details<content::ResourceRedirectDetails>(details).ptr();
658 bool is_top_level = resource_redirect_details->resource_type ==
659 content::RESOURCE_TYPE_MAIN_FRAME;
660 LoadRedirect(resource_redirect_details->url,
661 resource_redirect_details->new_url,
662 is_top_level);
663 break;
664 }
665 default:
666 NOTREACHED() << "Unexpected notification sent.";
667 break;
668 }
669 }
670
671 void WebViewGuest::StartFindInternal( 448 void WebViewGuest::StartFindInternal(
672 const base::string16& search_text, 449 const base::string16& search_text,
673 const blink::WebFindOptions& options, 450 const blink::WebFindOptions& options,
674 scoped_refptr<WebViewInternalFindFunction> find_function) { 451 scoped_refptr<WebViewInternalFindFunction> find_function) {
675 find_helper_.Find(web_contents(), search_text, options, find_function); 452 find_helper_.Find(web_contents(), search_text, options, find_function);
676 } 453 }
677 454
678 void WebViewGuest::StopFindingInternal(content::StopFindAction action) { 455 void WebViewGuest::StopFindingInternal(content::StopFindAction action) {
679 find_helper_.CancelAllFindSessions(); 456 find_helper_.CancelAllFindSessions();
680 web_contents()->StopFinding(action); 457 web_contents()->StopFinding(action);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 partition, remove_since, base::Time::Now()) 526 partition, remove_since, base::Time::Now())
750 ->Remove(cache_removal_done_callback); 527 ->Remove(cache_removal_done_callback);
751 528
752 return true; 529 return true;
753 } 530 }
754 531
755 ClearDataInternal(remove_since, removal_mask, callback); 532 ClearDataInternal(remove_since, removal_mask, callback);
756 return true; 533 return true;
757 } 534 }
758 535
759 WebViewGuest::WebViewGuest(WebContents* owner_web_contents) 536 void WebViewGuest::ClearDataInternal(base::Time remove_since,
760 : GuestView<WebViewGuest>(owner_web_contents), 537 uint32 removal_mask,
761 rules_registry_id_(RulesRegistryService::kInvalidRulesRegistryID), 538 const base::Closure& callback) {
762 find_helper_(this), 539 uint32 storage_partition_removal_mask =
763 is_overriding_user_agent_(false), 540 GetStoragePartitionRemovalMask(removal_mask);
764 allow_transparency_(false), 541 if (!storage_partition_removal_mask) {
765 javascript_dialog_helper_(this), 542 callback.Run();
766 allow_scaling_(false), 543 return;
767 is_guest_fullscreen_(false), 544 }
768 is_embedder_fullscreen_(false), 545 content::StoragePartition* partition =
769 last_fullscreen_permission_was_allowed_by_embedder_(false), 546 content::BrowserContext::GetStoragePartition(
770 pending_zoom_factor_(0.0), 547 web_contents()->GetBrowserContext(),
771 weak_ptr_factory_(this) { 548 web_contents()->GetSiteInstance());
772 web_view_guest_delegate_.reset( 549 partition->ClearData(
773 ExtensionsAPIClient::Get()->CreateWebViewGuestDelegate(this)); 550 storage_partition_removal_mask,
774 } 551 content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, GURL(),
775 552 content::StoragePartition::OriginMatcherFunction(), remove_since,
776 WebViewGuest::~WebViewGuest() { 553 base::Time::Now(), callback);
777 } 554 }
778 555
779 void WebViewGuest::DidCommitProvisionalLoadForFrame( 556 void WebViewGuest::OnWebViewNewWindowResponse(int new_window_instance_id,
780 content::RenderFrameHost* render_frame_host, 557 bool allow,
781 const GURL& url, 558 const std::string& user_input) {
782 ui::PageTransition transition_type) { 559 auto guest =
783 if (!render_frame_host->GetParent()) { 560 WebViewGuest::From(owner_web_contents()->GetRenderProcessHost()->GetID(),
784 src_ = url; 561 new_window_instance_id);
785 // Handle a pending zoom if one exists. 562 if (!guest)
786 if (pending_zoom_factor_) { 563 return;
787 SetZoom(pending_zoom_factor_); 564
788 pending_zoom_factor_ = 0.0; 565 if (!allow)
789 } 566 guest->Destroy();
790 } 567 }
568
569 void WebViewGuest::OnFullscreenPermissionDecided(
570 bool allowed,
571 const std::string& user_input) {
572 last_fullscreen_permission_was_allowed_by_embedder_ = allowed;
573 SetFullscreenState(allowed);
574 }
575
576 bool WebViewGuest::GuestMadeEmbedderFullscreen() const {
577 return last_fullscreen_permission_was_allowed_by_embedder_ &&
578 is_embedder_fullscreen_;
579 }
580
581 void WebViewGuest::SetFullscreenState(bool is_fullscreen) {
582 if (is_fullscreen == is_guest_fullscreen_)
583 return;
584
585 bool was_fullscreen = is_guest_fullscreen_;
586 is_guest_fullscreen_ = is_fullscreen;
587 // If the embedder entered fullscreen because of us, it should exit fullscreen
588 // when we exit fullscreen.
589 if (was_fullscreen && GuestMadeEmbedderFullscreen()) {
590 // Dispatch a message so we can call document.webkitCancelFullscreen()
591 // on the embedder.
592 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
593 DispatchEventToView(
594 new GuestViewEvent(webview::kEventExitFullscreen, args.Pass()));
595 }
596 // Since we changed fullscreen state, sending a Resize message ensures that
597 // renderer/ sees the change.
598 web_contents()->GetRenderViewHost()->WasResized();
599 }
600
601 bool WebViewGuest::CanRunInDetachedState() const {
602 return true;
603 }
604
605 void WebViewGuest::CreateWebContents(
606 const base::DictionaryValue& create_params,
607 const WebContentsCreatedCallback& callback) {
608 RenderProcessHost* owner_render_process_host =
609 owner_web_contents()->GetRenderProcessHost();
610 std::string storage_partition_id;
611 bool persist_storage = false;
612 ParsePartitionParam(create_params, &storage_partition_id, &persist_storage);
613 // Validate that the partition id coming from the renderer is valid UTF-8,
614 // since we depend on this in other parts of the code, such as FilePath
615 // creation. If the validation fails, treat it as a bad message and kill the
616 // renderer process.
617 if (!base::IsStringUTF8(storage_partition_id)) {
618 content::RecordAction(base::UserMetricsAction("BadMessageTerminate_BPGM"));
619 owner_render_process_host->Shutdown(content::RESULT_CODE_KILLED_BAD_MESSAGE,
620 false);
621 callback.Run(nullptr);
622 return;
623 }
624 std::string url_encoded_partition =
625 net::EscapeQueryParamValue(storage_partition_id, false);
626 std::string partition_domain = GetOwnerSiteURL().host();
627 GURL guest_site(base::StringPrintf(
628 "%s://%s/%s?%s", content::kGuestScheme, partition_domain.c_str(),
629 persist_storage ? "persist" : "", url_encoded_partition.c_str()));
630
631 // If we already have a webview tag in the same app using the same storage
632 // partition, we should use the same SiteInstance so the existing tag and
633 // the new tag can script each other.
634 auto guest_view_manager = GuestViewManager::FromBrowserContext(
635 owner_render_process_host->GetBrowserContext());
636 content::SiteInstance* guest_site_instance =
637 guest_view_manager->GetGuestSiteInstance(guest_site);
638 if (!guest_site_instance) {
639 // Create the SiteInstance in a new BrowsingInstance, which will ensure
640 // that webview tags are also not allowed to send messages across
641 // different partitions.
642 guest_site_instance = content::SiteInstance::CreateForURL(
643 owner_render_process_host->GetBrowserContext(), guest_site);
644 }
645 WebContents::CreateParams params(
646 owner_render_process_host->GetBrowserContext(), guest_site_instance);
647 params.guest_delegate = this;
648 callback.Run(WebContents::Create(params));
649 }
650
651 void WebViewGuest::DidAttachToEmbedder() {
652 ApplyAttributes(*attach_params());
653 }
654
655 void WebViewGuest::DidDropLink(const GURL& url) {
791 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue()); 656 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
792 args->SetString(guest_view::kUrl, url.spec()); 657 args->SetString(guest_view::kUrl, url.spec());
793 args->SetBoolean(guest_view::kIsTopLevel, !render_frame_host->GetParent()); 658 DispatchEventToView(new GuestViewEvent(webview::kEventDropLink, args.Pass()));
794 args->SetString(webview::kInternalBaseURLForDataURL, 659 }
795 web_contents() 660
796 ->GetController() 661 void WebViewGuest::DidInitialize(const base::DictionaryValue& create_params) {
797 .GetLastCommittedEntry() 662 script_executor_.reset(
798 ->GetBaseURLForDataURL() 663 new ScriptExecutor(web_contents(), &script_observers_));
799 .spec()); 664
800 args->SetInteger(webview::kInternalCurrentEntryIndex, 665 notification_registrar_.Add(this,
801 web_contents()->GetController().GetCurrentEntryIndex()); 666 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
802 args->SetInteger(webview::kInternalEntryCount, 667 content::Source<WebContents>(web_contents()));
803 web_contents()->GetController().GetEntryCount()); 668
804 args->SetInteger(webview::kInternalProcessId, 669 notification_registrar_.Add(this,
805 web_contents()->GetRenderProcessHost()->GetID()); 670 content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
671 content::Source<WebContents>(web_contents()));
672
673 if (web_view_guest_delegate_)
674 web_view_guest_delegate_->OnDidInitialize();
675 ExtensionsAPIClient::Get()->AttachWebContentsHelpers(web_contents());
676 web_view_permission_helper_.reset(new WebViewPermissionHelper(this));
677
678 rules_registry_id_ = GetOrGenerateRulesRegistryID(
679 owner_web_contents()->GetRenderProcessHost()->GetID(),
680 view_instance_id());
681
682 // We must install the mapping from guests to WebViews prior to resuming
683 // suspended resource loads so that the WebRequest API will catch resource
684 // requests.
685 PushWebViewStateToIOThread();
686
687 ApplyAttributes(create_params);
688 }
689
690 void WebViewGuest::EmbedderFullscreenToggled(bool entered_fullscreen) {
691 is_embedder_fullscreen_ = entered_fullscreen;
692 // If the embedder has got out of fullscreen, we get out of fullscreen
693 // mode as well.
694 if (!entered_fullscreen)
695 SetFullscreenState(false);
696 }
697
698 void WebViewGuest::FindReply(WebContents* source,
699 int request_id,
700 int number_of_matches,
701 const gfx::Rect& selection_rect,
702 int active_match_ordinal,
703 bool final_update) {
704 GuestViewBase::FindReply(source, request_id, number_of_matches,
705 selection_rect, active_match_ordinal, final_update);
706 find_helper_.FindReply(request_id, number_of_matches, selection_rect,
707 active_match_ordinal, final_update);
708 }
709
710 const char* WebViewGuest::GetAPINamespace() const {
711 return webview::kAPINamespace;
712 }
713
714 int WebViewGuest::GetTaskPrefix() const {
715 return IDS_EXTENSION_TASK_MANAGER_WEBVIEW_TAG_PREFIX;
716 }
717
718 void WebViewGuest::GuestDestroyed() {
719 RemoveWebViewStateFromIOThread(web_contents());
720 }
721
722 void WebViewGuest::GuestReady() {
723 // The guest RenderView should always live in an isolated guest process.
724 CHECK(web_contents()->GetRenderProcessHost()->IsForGuestsOnly());
725 Send(new ExtensionMsg_SetFrameName(web_contents()->GetRoutingID(), name_));
726
727 // We don't want to accidentally set the opacity of an interstitial page.
728 // WebContents::GetRenderWidgetHostView will return the RWHV of an
729 // interstitial page if one is showing at this time. We only want opacity
730 // to apply to web pages.
731 if (allow_transparency_) {
732 web_contents()->GetRenderViewHost()->GetView()->SetBackgroundColor(
733 SK_ColorTRANSPARENT);
734 } else {
735 web_contents()
736 ->GetRenderViewHost()
737 ->GetView()
738 ->SetBackgroundColorToDefault();
739 }
740 }
741
742 void WebViewGuest::GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
743 const gfx::Size& new_size) {
744 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
745 args->SetInteger(webview::kOldHeight, old_size.height());
746 args->SetInteger(webview::kOldWidth, old_size.width());
747 args->SetInteger(webview::kNewHeight, new_size.height());
748 args->SetInteger(webview::kNewWidth, new_size.width());
806 DispatchEventToView( 749 DispatchEventToView(
807 new GuestViewEvent(webview::kEventLoadCommit, args.Pass())); 750 new GuestViewEvent(webview::kEventSizeChanged, args.Pass()));
808 751 }
809 find_helper_.CancelAllFindSessions(); 752
810 } 753 void WebViewGuest::GuestViewDidStopLoading() {
811 754 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
812 void WebViewGuest::DidFailProvisionalLoad( 755 DispatchEventToView(new GuestViewEvent(webview::kEventLoadStop, args.Pass()));
813 content::RenderFrameHost* render_frame_host, 756 }
814 const GURL& validated_url, 757
815 int error_code, 758 void WebViewGuest::GuestZoomChanged(double old_zoom_level,
816 const base::string16& error_description, 759 double new_zoom_level) {
817 bool was_ignored_by_handler) { 760 // Dispatch the zoomchange event.
818 // Suppress loadabort for "mailto" URLs. 761 double old_zoom_factor = ConvertZoomLevelToZoomFactor(old_zoom_level);
819 if (validated_url.SchemeIs(url::kMailToScheme)) 762 double new_zoom_factor = ConvertZoomLevelToZoomFactor(new_zoom_level);
820 return; 763 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
821 764 args->SetDouble(webview::kOldZoomFactor, old_zoom_factor);
822 LoadAbort(!render_frame_host->GetParent(), validated_url, error_code, 765 args->SetDouble(webview::kNewZoomFactor, new_zoom_factor);
823 net::ErrorToShortString(error_code));
824 }
825
826 void WebViewGuest::DidStartProvisionalLoadForFrame(
827 content::RenderFrameHost* render_frame_host,
828 const GURL& validated_url,
829 bool is_error_page,
830 bool is_iframe_srcdoc) {
831 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
832 args->SetString(guest_view::kUrl, validated_url.spec());
833 args->SetBoolean(guest_view::kIsTopLevel, !render_frame_host->GetParent());
834 DispatchEventToView( 766 DispatchEventToView(
835 new GuestViewEvent(webview::kEventLoadStart, args.Pass())); 767 new GuestViewEvent(webview::kEventZoomChange, args.Pass()));
836 } 768 }
837 769
838 void WebViewGuest::RenderProcessGone(base::TerminationStatus status) { 770 bool WebViewGuest::IsAutoSizeSupported() const {
839 // Cancel all find sessions in progress. 771 return true;
840 find_helper_.CancelAllFindSessions(); 772 }
841 773
842 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue()); 774 void WebViewGuest::SetContextMenuPosition(const gfx::Point& position) {
843 args->SetInteger(webview::kProcessId, 775 if (web_view_guest_delegate_)
844 web_contents()->GetRenderProcessHost()->GetID()); 776 web_view_guest_delegate_->SetContextMenuPosition(position);
845 args->SetString(webview::kReason, TerminationStatusToString(status));
846 DispatchEventToView(
847 new GuestViewEvent(webview::kEventExit, args.Pass()));
848 }
849
850 void WebViewGuest::UserAgentOverrideSet(const std::string& user_agent) {
851 content::NavigationController& controller = web_contents()->GetController();
852 content::NavigationEntry* entry = controller.GetVisibleEntry();
853 if (!entry)
854 return;
855 entry->SetIsOverridingUserAgent(!user_agent.empty());
856 web_contents()->GetController().Reload(false);
857 }
858
859 void WebViewGuest::FrameNameChanged(RenderFrameHost* render_frame_host,
860 const std::string& name) {
861 if (render_frame_host->GetParent())
862 return;
863
864 if (name_ == name)
865 return;
866
867 ReportFrameNameChange(name);
868 }
869
870 void WebViewGuest::ReportFrameNameChange(const std::string& name) {
871 name_ = name;
872 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
873 args->SetString(webview::kName, name);
874 DispatchEventToView(
875 new GuestViewEvent(webview::kEventFrameNameChanged, args.Pass()));
876 }
877
878 void WebViewGuest::LoadHandlerCalled() {
879 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
880 DispatchEventToView(
881 new GuestViewEvent(webview::kEventContentLoad, args.Pass()));
882 }
883
884 void WebViewGuest::LoadRedirect(const GURL& old_url,
885 const GURL& new_url,
886 bool is_top_level) {
887 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
888 args->SetBoolean(guest_view::kIsTopLevel, is_top_level);
889 args->SetString(webview::kNewURL, new_url.spec());
890 args->SetString(webview::kOldURL, old_url.spec());
891 DispatchEventToView(
892 new GuestViewEvent(webview::kEventLoadRedirect, args.Pass()));
893 }
894
895 void WebViewGuest::PushWebViewStateToIOThread() {
896 const GURL& site_url = web_contents()->GetSiteInstance()->GetSiteURL();
897 std::string partition_domain;
898 std::string partition_id;
899 bool in_memory;
900 if (!GetGuestPartitionConfigForSite(
901 site_url, &partition_domain, &partition_id, &in_memory)) {
902 NOTREACHED();
903 return;
904 }
905
906 WebViewRendererState::WebViewInfo web_view_info;
907 web_view_info.embedder_process_id =
908 owner_web_contents()->GetRenderProcessHost()->GetID();
909 web_view_info.instance_id = view_instance_id();
910 web_view_info.partition_id = partition_id;
911 web_view_info.owner_host = owner_host();
912 web_view_info.rules_registry_id = rules_registry_id_;
913
914 // Get content scripts IDs added by the guest.
915 WebViewContentScriptManager* manager =
916 WebViewContentScriptManager::Get(browser_context());
917 DCHECK(manager);
918 web_view_info.content_script_ids = manager->GetContentScriptIDSet(
919 web_view_info.embedder_process_id, web_view_info.instance_id);
920
921 content::BrowserThread::PostTask(
922 content::BrowserThread::IO,
923 FROM_HERE,
924 base::Bind(&WebViewRendererState::AddGuest,
925 base::Unretained(WebViewRendererState::GetInstance()),
926 web_contents()->GetRenderProcessHost()->GetID(),
927 web_contents()->GetRoutingID(),
928 web_view_info));
929 }
930
931 // static
932 void WebViewGuest::RemoveWebViewStateFromIOThread(
933 WebContents* web_contents) {
934 content::BrowserThread::PostTask(
935 content::BrowserThread::IO, FROM_HERE,
936 base::Bind(
937 &WebViewRendererState::RemoveGuest,
938 base::Unretained(WebViewRendererState::GetInstance()),
939 web_contents->GetRenderProcessHost()->GetID(),
940 web_contents->GetRoutingID()));
941 }
942
943 void WebViewGuest::RequestMediaAccessPermission(
944 WebContents* source,
945 const content::MediaStreamRequest& request,
946 const content::MediaResponseCallback& callback) {
947 web_view_permission_helper_->RequestMediaAccessPermission(source,
948 request,
949 callback);
950 }
951
952 bool WebViewGuest::CheckMediaAccessPermission(WebContents* source,
953 const GURL& security_origin,
954 content::MediaStreamType type) {
955 return web_view_permission_helper_->CheckMediaAccessPermission(
956 source, security_origin, type);
957 }
958
959 void WebViewGuest::CanDownload(
960 const GURL& url,
961 const std::string& request_method,
962 const base::Callback<void(bool)>& callback) {
963 web_view_permission_helper_->CanDownload(url, request_method, callback);
964 }
965
966 void WebViewGuest::RequestPointerLockPermission(
967 bool user_gesture,
968 bool last_unlocked_by_target,
969 const base::Callback<void(bool)>& callback) {
970 web_view_permission_helper_->RequestPointerLockPermission(
971 user_gesture,
972 last_unlocked_by_target,
973 callback);
974 } 777 }
975 778
976 void WebViewGuest::SignalWhenReady(const base::Closure& callback) { 779 void WebViewGuest::SignalWhenReady(const base::Closure& callback) {
977 auto manager = WebViewContentScriptManager::Get(browser_context()); 780 auto manager = WebViewContentScriptManager::Get(browser_context());
978 manager->SignalOnScriptsLoaded(callback); 781 manager->SignalOnScriptsLoaded(callback);
979 } 782 }
980 783
981 bool WebViewGuest::ShouldHandleFindRequestsForEmbedder() const { 784 bool WebViewGuest::ShouldHandleFindRequestsForEmbedder() const {
982 if (web_view_guest_delegate_) 785 if (web_view_guest_delegate_)
983 return web_view_guest_delegate_->ShouldHandleFindRequestsForEmbedder(); 786 return web_view_guest_delegate_->ShouldHandleFindRequestsForEmbedder();
984 return false; 787 return false;
985 } 788 }
986 789
987 void WebViewGuest::WillAttachToEmbedder() { 790 void WebViewGuest::WillAttachToEmbedder() {
988 rules_registry_id_ = GetOrGenerateRulesRegistryID( 791 rules_registry_id_ = GetOrGenerateRulesRegistryID(
989 owner_web_contents()->GetRenderProcessHost()->GetID(), 792 owner_web_contents()->GetRenderProcessHost()->GetID(),
990 view_instance_id()); 793 view_instance_id());
991 794
992 // We must install the mapping from guests to WebViews prior to resuming 795 // We must install the mapping from guests to WebViews prior to resuming
993 // suspended resource loads so that the WebRequest API will catch resource 796 // suspended resource loads so that the WebRequest API will catch resource
994 // requests. 797 // requests.
995 PushWebViewStateToIOThread(); 798 PushWebViewStateToIOThread();
996 } 799 }
997 800
801 void WebViewGuest::WillDestroy() {
802 if (!attached() && GetOpener())
803 GetOpener()->pending_new_windows_.erase(this);
804 }
805
806 void WebViewGuest::Observe(int type,
807 const content::NotificationSource& source,
808 const content::NotificationDetails& details) {
809 switch (type) {
810 case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: {
811 DCHECK_EQ(content::Source<WebContents>(source).ptr(), web_contents());
812 if (content::Source<WebContents>(source).ptr() == web_contents())
813 LoadHandlerCalled();
814 break;
815 }
816 case content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: {
817 DCHECK_EQ(content::Source<WebContents>(source).ptr(), web_contents());
818 content::ResourceRedirectDetails* resource_redirect_details =
819 content::Details<content::ResourceRedirectDetails>(details).ptr();
820 bool is_top_level = resource_redirect_details->resource_type ==
821 content::RESOURCE_TYPE_MAIN_FRAME;
822 LoadRedirect(resource_redirect_details->url,
823 resource_redirect_details->new_url, is_top_level);
824 break;
825 }
826 default:
827 NOTREACHED() << "Unexpected notification sent.";
828 break;
829 }
830 }
831
832 bool WebViewGuest::AddMessageToConsole(WebContents* source,
833 int32 level,
834 const base::string16& message,
835 int32 line_no,
836 const base::string16& source_id) {
837 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
838 // Log levels are from base/logging.h: LogSeverity.
839 args->SetInteger(webview::kLevel, level);
840 args->SetString(webview::kMessage, message);
841 args->SetInteger(webview::kLine, line_no);
842 args->SetString(webview::kSourceId, source_id);
843 DispatchEventToView(
844 new GuestViewEvent(webview::kEventConsoleMessage, args.Pass()));
845 return true;
846 }
847
848 void WebViewGuest::CloseContents(WebContents* source) {
849 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
850 DispatchEventToView(new GuestViewEvent(webview::kEventClose, args.Pass()));
851 }
852
853 bool WebViewGuest::HandleContextMenu(const content::ContextMenuParams& params) {
854 if (!web_view_guest_delegate_)
855 return false;
856 return web_view_guest_delegate_->HandleContextMenu(params);
857 }
858
859 void WebViewGuest::HandleKeyboardEvent(
860 WebContents* source,
861 const content::NativeWebKeyboardEvent& event) {
862 if (HandleKeyboardShortcuts(event))
863 return;
864
865 GuestViewBase::HandleKeyboardEvent(source, event);
866 }
867
868 void WebViewGuest::LoadProgressChanged(WebContents* source, double progress) {
869 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
870 args->SetString(guest_view::kUrl, web_contents()->GetURL().spec());
871 args->SetDouble(webview::kProgress, progress);
872 DispatchEventToView(
873 new GuestViewEvent(webview::kEventLoadProgress, args.Pass()));
874 }
875
876 bool WebViewGuest::PreHandleGestureEvent(WebContents* source,
877 const blink::WebGestureEvent& event) {
878 return !allow_scaling_ && GuestViewBase::PreHandleGestureEvent(source, event);
879 }
880
881 // TODO(fsamuel): Find a reliable way to test the 'responsive' and
882 // 'unresponsive' events.
883 void WebViewGuest::RendererResponsive(WebContents* source) {
884 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
885 args->SetInteger(webview::kProcessId,
886 web_contents()->GetRenderProcessHost()->GetID());
887 DispatchEventToView(
888 new GuestViewEvent(webview::kEventResponsive, args.Pass()));
889 }
890
891 void WebViewGuest::RendererUnresponsive(WebContents* source) {
892 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
893 args->SetInteger(webview::kProcessId,
894 web_contents()->GetRenderProcessHost()->GetID());
895 DispatchEventToView(
896 new GuestViewEvent(webview::kEventUnresponsive, args.Pass()));
897 }
898
899 void WebViewGuest::RequestMediaAccessPermission(
900 WebContents* source,
901 const content::MediaStreamRequest& request,
902 const content::MediaResponseCallback& callback) {
903 web_view_permission_helper_->RequestMediaAccessPermission(source, request,
904 callback);
905 }
906
907 void WebViewGuest::RequestPointerLockPermission(
908 bool user_gesture,
909 bool last_unlocked_by_target,
910 const base::Callback<void(bool)>& callback) {
911 web_view_permission_helper_->RequestPointerLockPermission(
912 user_gesture, last_unlocked_by_target, callback);
913 }
914
915 bool WebViewGuest::CheckMediaAccessPermission(WebContents* source,
916 const GURL& security_origin,
917 content::MediaStreamType type) {
918 return web_view_permission_helper_->CheckMediaAccessPermission(
919 source, security_origin, type);
920 }
921
922 void WebViewGuest::CanDownload(const GURL& url,
923 const std::string& request_method,
924 const base::Callback<void(bool)>& callback) {
925 web_view_permission_helper_->CanDownload(url, request_method, callback);
926 }
927
998 content::JavaScriptDialogManager* WebViewGuest::GetJavaScriptDialogManager( 928 content::JavaScriptDialogManager* WebViewGuest::GetJavaScriptDialogManager(
999 WebContents* source) { 929 WebContents* source) {
1000 return &javascript_dialog_helper_; 930 return &javascript_dialog_helper_;
1001 } 931 }
1002 932
1003 void WebViewGuest::NavigateGuest(const std::string& src,
1004 bool force_navigation) {
1005 if (src.empty())
1006 return;
1007
1008 GURL url = ResolveURL(src);
1009
1010 // We wait for all the content scripts to load and then navigate the guest
1011 // if the navigation is embedder-initiated. For browser-initiated navigations,
1012 // content scripts will be ready.
1013 if (force_navigation) {
1014 SignalWhenReady(base::Bind(
1015 &WebViewGuest::LoadURLWithParams, weak_ptr_factory_.GetWeakPtr(), url,
1016 content::Referrer(), ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
1017 GlobalRequestID(), force_navigation));
1018 return;
1019 }
1020 LoadURLWithParams(url, content::Referrer(), ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
1021 GlobalRequestID(), force_navigation);
1022 }
1023
1024 bool WebViewGuest::HandleKeyboardShortcuts(
1025 const content::NativeWebKeyboardEvent& event) {
1026 // <webview> outside of Chrome Apps do not handle keyboard shortcuts.
1027 if (!GuestViewManager::FromBrowserContext(browser_context())->
1028 IsOwnedByExtension(this)) {
1029 return false;
1030 }
1031
1032 if (event.type != blink::WebInputEvent::RawKeyDown)
1033 return false;
1034
1035 // If the user hits the escape key without any modifiers then unlock the
1036 // mouse if necessary.
1037 if ((event.windowsKeyCode == ui::VKEY_ESCAPE) &&
1038 !(event.modifiers & blink::WebInputEvent::InputModifiers)) {
1039 return web_contents()->GotResponseToLockMouseRequest(false);
1040 }
1041
1042 #if defined(OS_MACOSX)
1043 if (event.modifiers != blink::WebInputEvent::MetaKey)
1044 return false;
1045
1046 if (event.windowsKeyCode == ui::VKEY_OEM_4) {
1047 Go(-1);
1048 return true;
1049 }
1050
1051 if (event.windowsKeyCode == ui::VKEY_OEM_6) {
1052 Go(1);
1053 return true;
1054 }
1055 #else
1056 if (event.windowsKeyCode == ui::VKEY_BROWSER_BACK) {
1057 Go(-1);
1058 return true;
1059 }
1060
1061 if (event.windowsKeyCode == ui::VKEY_BROWSER_FORWARD) {
1062 Go(1);
1063 return true;
1064 }
1065 #endif
1066
1067 return false;
1068 }
1069
1070 void WebViewGuest::ApplyAttributes(const base::DictionaryValue& params) {
1071 std::string name;
1072 if (params.GetString(webview::kAttributeName, &name)) {
1073 // If the guest window's name is empty, then the WebView tag's name is
1074 // assigned. Otherwise, the guest window's name takes precedence over the
1075 // WebView tag's name.
1076 if (name_.empty())
1077 SetName(name);
1078 }
1079 if (attached())
1080 ReportFrameNameChange(name_);
1081
1082 std::string user_agent_override;
1083 params.GetString(webview::kParameterUserAgentOverride, &user_agent_override);
1084 SetUserAgentOverride(user_agent_override);
1085
1086 bool allow_transparency = false;
1087 if (params.GetBoolean(webview::kAttributeAllowTransparency,
1088 &allow_transparency)) {
1089 // We need to set the background opaque flag after navigation to ensure that
1090 // there is a RenderWidgetHostView available.
1091 SetAllowTransparency(allow_transparency);
1092 }
1093
1094 bool allow_scaling = false;
1095 if (params.GetBoolean(webview::kAttributeAllowScaling, &allow_scaling))
1096 SetAllowScaling(allow_scaling);
1097
1098 // Check for a pending zoom from before the first navigation.
1099 params.GetDouble(webview::kInitialZoomFactor, &pending_zoom_factor_);
1100
1101 bool is_pending_new_window = false;
1102 if (GetOpener()) {
1103 // We need to do a navigation here if the target URL has changed between
1104 // the time the WebContents was created and the time it was attached.
1105 // We also need to do an initial navigation if a RenderView was never
1106 // created for the new window in cases where there is no referrer.
1107 auto it = GetOpener()->pending_new_windows_.find(this);
1108 if (it != GetOpener()->pending_new_windows_.end()) {
1109 const NewWindowInfo& new_window_info = it->second;
1110 if (new_window_info.changed || !web_contents()->HasOpener())
1111 NavigateGuest(new_window_info.url.spec(), false /* force_navigation */);
1112
1113 // Once a new guest is attached to the DOM of the embedder page, then the
1114 // lifetime of the new guest is no longer managed by the opener guest.
1115 GetOpener()->pending_new_windows_.erase(this);
1116
1117 is_pending_new_window = true;
1118 }
1119 }
1120
1121 // Only read the src attribute if this is not a New Window API flow.
1122 if (!is_pending_new_window) {
1123 std::string src;
1124 if (params.GetString(webview::kAttributeSrc, &src))
1125 NavigateGuest(src, true /* force_navigation */);
1126 }
1127 }
1128
1129 void WebViewGuest::ShowContextMenu(
1130 int request_id,
1131 const WebViewGuestDelegate::MenuItemVector* items) {
1132 if (web_view_guest_delegate_)
1133 web_view_guest_delegate_->OnShowContextMenu(request_id, items);
1134 }
1135
1136 void WebViewGuest::SetName(const std::string& name) {
1137 if (name_ == name)
1138 return;
1139 name_ = name;
1140
1141 Send(new ExtensionMsg_SetFrameName(routing_id(), name_));
1142 }
1143
1144 void WebViewGuest::SetZoom(double zoom_factor) {
1145 auto zoom_controller = ZoomController::FromWebContents(web_contents());
1146 DCHECK(zoom_controller);
1147 double zoom_level = content::ZoomFactorToZoomLevel(zoom_factor);
1148 zoom_controller->SetZoomLevel(zoom_level);
1149 }
1150
1151 void WebViewGuest::SetZoomMode(ZoomController::ZoomMode zoom_mode) {
1152 ZoomController::FromWebContents(web_contents())->SetZoomMode(zoom_mode);
1153 }
1154
1155 void WebViewGuest::SetAllowTransparency(bool allow) {
1156 if (allow_transparency_ == allow)
1157 return;
1158
1159 allow_transparency_ = allow;
1160 if (!web_contents()->GetRenderViewHost()->GetView())
1161 return;
1162
1163 if (allow_transparency_) {
1164 web_contents()->GetRenderViewHost()->GetView()->SetBackgroundColor(
1165 SK_ColorTRANSPARENT);
1166 } else {
1167 web_contents()
1168 ->GetRenderViewHost()
1169 ->GetView()
1170 ->SetBackgroundColorToDefault();
1171 }
1172 }
1173
1174 void WebViewGuest::SetAllowScaling(bool allow) {
1175 allow_scaling_ = allow;
1176 }
1177
1178 bool WebViewGuest::LoadDataWithBaseURL(const std::string& data_url,
1179 const std::string& base_url,
1180 const std::string& virtual_url,
1181 std::string* error) {
1182 // Make GURLs from URLs.
1183 const GURL data_gurl = GURL(data_url);
1184 const GURL base_gurl = GURL(base_url);
1185 const GURL virtual_gurl = GURL(virtual_url);
1186
1187 // Check that the provided URLs are valid.
1188 // |data_url| must be a valid data URL.
1189 if (!data_gurl.is_valid() || !data_gurl.SchemeIs(url::kDataScheme)) {
1190 base::SStringPrintf(
1191 error, webview::kAPILoadDataInvalidDataURL, data_url.c_str());
1192 return false;
1193 }
1194 // |base_url| must be a valid URL.
1195 if (!base_gurl.is_valid()) {
1196 base::SStringPrintf(
1197 error, webview::kAPILoadDataInvalidBaseURL, base_url.c_str());
1198 return false;
1199 }
1200 // |virtual_url| must be a valid URL.
1201 if (!virtual_gurl.is_valid()) {
1202 base::SStringPrintf(
1203 error, webview::kAPILoadDataInvalidVirtualURL, virtual_url.c_str());
1204 return false;
1205 }
1206
1207 // Set up the parameters to load |data_url| with the specified |base_url|.
1208 content::NavigationController::LoadURLParams load_params(data_gurl);
1209 load_params.load_type = content::NavigationController::LOAD_TYPE_DATA;
1210 load_params.base_url_for_data_url = base_gurl;
1211 load_params.virtual_url_for_data_url = virtual_gurl;
1212 load_params.override_user_agent =
1213 content::NavigationController::UA_OVERRIDE_INHERIT;
1214
1215 // Navigate to the data URL.
1216 GuestViewBase::LoadURLWithParams(load_params);
1217
1218 return true;
1219 }
1220
1221 void WebViewGuest::AddNewContents(WebContents* source, 933 void WebViewGuest::AddNewContents(WebContents* source,
1222 WebContents* new_contents, 934 WebContents* new_contents,
1223 WindowOpenDisposition disposition, 935 WindowOpenDisposition disposition,
1224 const gfx::Rect& initial_rect, 936 const gfx::Rect& initial_rect,
1225 bool user_gesture, 937 bool user_gesture,
1226 bool* was_blocked) { 938 bool* was_blocked) {
1227 if (was_blocked) 939 if (was_blocked)
1228 *was_blocked = false; 940 *was_blocked = false;
1229 RequestNewWindowPermission(disposition, 941 RequestNewWindowPermission(disposition,
1230 initial_rect, 942 initial_rect,
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1333 1045
1334 void WebViewGuest::ExitFullscreenModeForTab(WebContents* web_contents) { 1046 void WebViewGuest::ExitFullscreenModeForTab(WebContents* web_contents) {
1335 SetFullscreenState(false); 1047 SetFullscreenState(false);
1336 } 1048 }
1337 1049
1338 bool WebViewGuest::IsFullscreenForTabOrPending( 1050 bool WebViewGuest::IsFullscreenForTabOrPending(
1339 const WebContents* web_contents) const { 1051 const WebContents* web_contents) const {
1340 return is_guest_fullscreen_; 1052 return is_guest_fullscreen_;
1341 } 1053 }
1342 1054
1055 void WebViewGuest::DidCommitProvisionalLoadForFrame(
1056 content::RenderFrameHost* render_frame_host,
1057 const GURL& url,
1058 ui::PageTransition transition_type) {
1059 if (!render_frame_host->GetParent()) {
1060 src_ = url;
1061 // Handle a pending zoom if one exists.
1062 if (pending_zoom_factor_) {
1063 SetZoom(pending_zoom_factor_);
1064 pending_zoom_factor_ = 0.0;
1065 }
1066 }
1067 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
1068 args->SetString(guest_view::kUrl, url.spec());
1069 args->SetBoolean(guest_view::kIsTopLevel, !render_frame_host->GetParent());
1070 args->SetString(webview::kInternalBaseURLForDataURL,
1071 web_contents()
1072 ->GetController()
1073 .GetLastCommittedEntry()
1074 ->GetBaseURLForDataURL()
1075 .spec());
1076 args->SetInteger(webview::kInternalCurrentEntryIndex,
1077 web_contents()->GetController().GetCurrentEntryIndex());
1078 args->SetInteger(webview::kInternalEntryCount,
1079 web_contents()->GetController().GetEntryCount());
1080 args->SetInteger(webview::kInternalProcessId,
1081 web_contents()->GetRenderProcessHost()->GetID());
1082 DispatchEventToView(
1083 new GuestViewEvent(webview::kEventLoadCommit, args.Pass()));
1084
1085 find_helper_.CancelAllFindSessions();
1086 }
1087
1088 void WebViewGuest::DidFailProvisionalLoad(
1089 content::RenderFrameHost* render_frame_host,
1090 const GURL& validated_url,
1091 int error_code,
1092 const base::string16& error_description,
1093 bool was_ignored_by_handler) {
1094 // Suppress loadabort for "mailto" URLs.
1095 if (validated_url.SchemeIs(url::kMailToScheme))
1096 return;
1097
1098 LoadAbort(!render_frame_host->GetParent(), validated_url, error_code,
1099 net::ErrorToShortString(error_code));
1100 }
1101
1102 void WebViewGuest::DidStartProvisionalLoadForFrame(
1103 content::RenderFrameHost* render_frame_host,
1104 const GURL& validated_url,
1105 bool is_error_page,
1106 bool is_iframe_srcdoc) {
1107 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
1108 args->SetString(guest_view::kUrl, validated_url.spec());
1109 args->SetBoolean(guest_view::kIsTopLevel, !render_frame_host->GetParent());
1110 DispatchEventToView(
1111 new GuestViewEvent(webview::kEventLoadStart, args.Pass()));
1112 }
1113
1114 void WebViewGuest::RenderProcessGone(base::TerminationStatus status) {
1115 // Cancel all find sessions in progress.
1116 find_helper_.CancelAllFindSessions();
1117
1118 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
1119 args->SetInteger(webview::kProcessId,
1120 web_contents()->GetRenderProcessHost()->GetID());
1121 args->SetString(webview::kReason, TerminationStatusToString(status));
1122 DispatchEventToView(new GuestViewEvent(webview::kEventExit, args.Pass()));
1123 }
1124
1125 void WebViewGuest::UserAgentOverrideSet(const std::string& user_agent) {
1126 content::NavigationController& controller = web_contents()->GetController();
1127 content::NavigationEntry* entry = controller.GetVisibleEntry();
1128 if (!entry)
1129 return;
1130 entry->SetIsOverridingUserAgent(!user_agent.empty());
1131 web_contents()->GetController().Reload(false);
1132 }
1133
1134 void WebViewGuest::FrameNameChanged(RenderFrameHost* render_frame_host,
1135 const std::string& name) {
1136 if (render_frame_host->GetParent())
1137 return;
1138
1139 if (name_ == name)
1140 return;
1141
1142 ReportFrameNameChange(name);
1143 }
1144
1145 void WebViewGuest::ReportFrameNameChange(const std::string& name) {
1146 name_ = name;
1147 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
1148 args->SetString(webview::kName, name);
1149 DispatchEventToView(
1150 new GuestViewEvent(webview::kEventFrameNameChanged, args.Pass()));
1151 }
1152
1153 void WebViewGuest::LoadHandlerCalled() {
1154 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
1155 DispatchEventToView(
1156 new GuestViewEvent(webview::kEventContentLoad, args.Pass()));
1157 }
1158
1159 void WebViewGuest::LoadRedirect(const GURL& old_url,
1160 const GURL& new_url,
1161 bool is_top_level) {
1162 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
1163 args->SetBoolean(guest_view::kIsTopLevel, is_top_level);
1164 args->SetString(webview::kNewURL, new_url.spec());
1165 args->SetString(webview::kOldURL, old_url.spec());
1166 DispatchEventToView(
1167 new GuestViewEvent(webview::kEventLoadRedirect, args.Pass()));
1168 }
1169
1170 void WebViewGuest::PushWebViewStateToIOThread() {
1171 const GURL& site_url = web_contents()->GetSiteInstance()->GetSiteURL();
1172 std::string partition_domain;
1173 std::string partition_id;
1174 bool in_memory;
1175 if (!GetGuestPartitionConfigForSite(site_url, &partition_domain,
1176 &partition_id, &in_memory)) {
1177 NOTREACHED();
1178 return;
1179 }
1180
1181 WebViewRendererState::WebViewInfo web_view_info;
1182 web_view_info.embedder_process_id =
1183 owner_web_contents()->GetRenderProcessHost()->GetID();
1184 web_view_info.instance_id = view_instance_id();
1185 web_view_info.partition_id = partition_id;
1186 web_view_info.owner_host = owner_host();
1187 web_view_info.rules_registry_id = rules_registry_id_;
1188
1189 // Get content scripts IDs added by the guest.
1190 WebViewContentScriptManager* manager =
1191 WebViewContentScriptManager::Get(browser_context());
1192 DCHECK(manager);
1193 web_view_info.content_script_ids = manager->GetContentScriptIDSet(
1194 web_view_info.embedder_process_id, web_view_info.instance_id);
1195
1196 content::BrowserThread::PostTask(
1197 content::BrowserThread::IO, FROM_HERE,
1198 base::Bind(&WebViewRendererState::AddGuest,
1199 base::Unretained(WebViewRendererState::GetInstance()),
1200 web_contents()->GetRenderProcessHost()->GetID(),
1201 web_contents()->GetRoutingID(), web_view_info));
1202 }
1203
1204 // static
1205 void WebViewGuest::RemoveWebViewStateFromIOThread(WebContents* web_contents) {
1206 content::BrowserThread::PostTask(
1207 content::BrowserThread::IO, FROM_HERE,
1208 base::Bind(&WebViewRendererState::RemoveGuest,
1209 base::Unretained(WebViewRendererState::GetInstance()),
1210 web_contents->GetRenderProcessHost()->GetID(),
1211 web_contents->GetRoutingID()));
1212 }
1213
1343 void WebViewGuest::LoadURLWithParams( 1214 void WebViewGuest::LoadURLWithParams(
1344 const GURL& url, 1215 const GURL& url,
1345 const content::Referrer& referrer, 1216 const content::Referrer& referrer,
1346 ui::PageTransition transition_type, 1217 ui::PageTransition transition_type,
1347 const GlobalRequestID& transferred_global_request_id, 1218 const GlobalRequestID& transferred_global_request_id,
1348 bool force_navigation) { 1219 bool force_navigation) {
1349 if (!url.is_valid()) { 1220 if (!url.is_valid()) {
1350 LoadAbort(true /* is_top_level */, url, net::ERR_INVALID_URL, 1221 LoadAbort(true /* is_top_level */, url, net::ERR_INVALID_URL,
1351 net::ErrorToShortString(net::ERR_INVALID_URL)); 1222 net::ErrorToShortString(net::ERR_INVALID_URL));
1352 NavigateGuest(url::kAboutBlankURL, false /* force_navigation */); 1223 NavigateGuest(url::kAboutBlankURL, false /* force_navigation */);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1437 IsOwnedByExtension(this)) { 1308 IsOwnedByExtension(this)) {
1438 return GURL(src); 1309 return GURL(src);
1439 } 1310 }
1440 1311
1441 GURL default_url(base::StringPrintf("%s://%s/", 1312 GURL default_url(base::StringPrintf("%s://%s/",
1442 kExtensionScheme, 1313 kExtensionScheme,
1443 owner_host().c_str())); 1314 owner_host().c_str()));
1444 return default_url.Resolve(src); 1315 return default_url.Resolve(src);
1445 } 1316 }
1446 1317
1447 void WebViewGuest::OnWebViewNewWindowResponse( 1318 void WebViewGuest::LoadAbort(bool is_top_level,
1448 int new_window_instance_id, 1319 const GURL& url,
1449 bool allow, 1320 int error_code,
1450 const std::string& user_input) { 1321 const std::string& error_type) {
1451 auto guest = 1322 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
1452 WebViewGuest::From(owner_web_contents()->GetRenderProcessHost()->GetID(), 1323 args->SetBoolean(guest_view::kIsTopLevel, is_top_level);
1453 new_window_instance_id); 1324 args->SetString(guest_view::kUrl, url.possibly_invalid_spec());
1454 if (!guest) 1325 args->SetInteger(guest_view::kCode, error_code);
1455 return; 1326 args->SetString(guest_view::kReason, error_type);
1456 1327 DispatchEventToView(
1457 if (!allow) 1328 new GuestViewEvent(webview::kEventLoadAbort, args.Pass()));
1458 guest->Destroy();
1459 } 1329 }
1460 1330
1461 void WebViewGuest::OnFullscreenPermissionDecided( 1331 void WebViewGuest::CreateNewGuestWebViewWindow(
1462 bool allowed, 1332 const content::OpenURLParams& params) {
1463 const std::string& user_input) { 1333 GuestViewManager* guest_manager =
1464 last_fullscreen_permission_was_allowed_by_embedder_ = allowed; 1334 GuestViewManager::FromBrowserContext(browser_context());
1465 SetFullscreenState(allowed); 1335 // Set the attach params to use the same partition as the opener.
1336 // We pull the partition information from the site's URL, which is of the
1337 // form guest://site/{persist}?{partition_name}.
1338 const GURL& site_url = web_contents()->GetSiteInstance()->GetSiteURL();
1339 const std::string storage_partition_id =
1340 GetStoragePartitionIdFromSiteURL(site_url);
1341 base::DictionaryValue create_params;
1342 create_params.SetString(webview::kStoragePartitionId, storage_partition_id);
1343
1344 guest_manager->CreateGuest(
1345 WebViewGuest::Type, embedder_web_contents(), create_params,
1346 base::Bind(&WebViewGuest::NewGuestWebViewCallback,
1347 weak_ptr_factory_.GetWeakPtr(), params));
1466 } 1348 }
1467 1349
1468 bool WebViewGuest::GuestMadeEmbedderFullscreen() const { 1350 void WebViewGuest::NewGuestWebViewCallback(const content::OpenURLParams& params,
1469 return last_fullscreen_permission_was_allowed_by_embedder_ && 1351 WebContents* guest_web_contents) {
1470 is_embedder_fullscreen_; 1352 WebViewGuest* new_guest = WebViewGuest::FromWebContents(guest_web_contents);
1353 new_guest->SetOpener(this);
1354
1355 // Take ownership of |new_guest|.
1356 pending_new_windows_.insert(
1357 std::make_pair(new_guest, NewWindowInfo(params.url, std::string())));
1358
1359 // Request permission to show the new window.
1360 RequestNewWindowPermission(params.disposition, gfx::Rect(),
1361 params.user_gesture, new_guest->web_contents());
1471 } 1362 }
1472 1363
1473 void WebViewGuest::SetFullscreenState(bool is_fullscreen) { 1364 bool WebViewGuest::HandleKeyboardShortcuts(
1474 if (is_fullscreen == is_guest_fullscreen_) 1365 const content::NativeWebKeyboardEvent& event) {
1475 return; 1366 // <webview> outside of Chrome Apps do not handle keyboard shortcuts.
1367 if (!GuestViewManager::FromBrowserContext(browser_context())
1368 ->IsOwnedByExtension(this)) {
1369 return false;
1370 }
1476 1371
1477 bool was_fullscreen = is_guest_fullscreen_; 1372 if (event.type != blink::WebInputEvent::RawKeyDown)
1478 is_guest_fullscreen_ = is_fullscreen; 1373 return false;
1479 // If the embedder entered fullscreen because of us, it should exit fullscreen 1374
1480 // when we exit fullscreen. 1375 // If the user hits the escape key without any modifiers then unlock the
1481 if (was_fullscreen && GuestMadeEmbedderFullscreen()) { 1376 // mouse if necessary.
1482 // Dispatch a message so we can call document.webkitCancelFullscreen() 1377 if ((event.windowsKeyCode == ui::VKEY_ESCAPE) &&
1483 // on the embedder. 1378 !(event.modifiers & blink::WebInputEvent::InputModifiers)) {
1484 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue()); 1379 return web_contents()->GotResponseToLockMouseRequest(false);
1485 DispatchEventToView(
1486 new GuestViewEvent(webview::kEventExitFullscreen, args.Pass()));
1487 } 1380 }
1488 // Since we changed fullscreen state, sending a Resize message ensures that 1381
1489 // renderer/ sees the change. 1382 #if defined(OS_MACOSX)
1490 web_contents()->GetRenderViewHost()->WasResized(); 1383 if (event.modifiers != blink::WebInputEvent::MetaKey)
1384 return false;
1385
1386 if (event.windowsKeyCode == ui::VKEY_OEM_4) {
1387 Go(-1);
1388 return true;
1389 }
1390
1391 if (event.windowsKeyCode == ui::VKEY_OEM_6) {
1392 Go(1);
1393 return true;
1394 }
1395 #else
1396 if (event.windowsKeyCode == ui::VKEY_BROWSER_BACK) {
1397 Go(-1);
1398 return true;
1399 }
1400
1401 if (event.windowsKeyCode == ui::VKEY_BROWSER_FORWARD) {
1402 Go(1);
1403 return true;
1404 }
1405 #endif
1406
1407 return false;
1408 }
1409
1410 void WebViewGuest::ApplyAttributes(const base::DictionaryValue& params) {
1411 std::string name;
1412 if (params.GetString(webview::kAttributeName, &name)) {
1413 // If the guest window's name is empty, then the WebView tag's name is
1414 // assigned. Otherwise, the guest window's name takes precedence over the
1415 // WebView tag's name.
1416 if (name_.empty())
1417 SetName(name);
1418 }
1419 if (attached())
1420 ReportFrameNameChange(name_);
1421
1422 std::string user_agent_override;
1423 params.GetString(webview::kParameterUserAgentOverride, &user_agent_override);
1424 SetUserAgentOverride(user_agent_override);
1425
1426 bool allow_transparency = false;
1427 if (params.GetBoolean(webview::kAttributeAllowTransparency,
1428 &allow_transparency)) {
1429 // We need to set the background opaque flag after navigation to ensure that
1430 // there is a RenderWidgetHostView available.
1431 SetAllowTransparency(allow_transparency);
1432 }
1433
1434 bool allow_scaling = false;
1435 if (params.GetBoolean(webview::kAttributeAllowScaling, &allow_scaling))
1436 SetAllowScaling(allow_scaling);
1437
1438 // Check for a pending zoom from before the first navigation.
1439 params.GetDouble(webview::kInitialZoomFactor, &pending_zoom_factor_);
1440
1441 bool is_pending_new_window = false;
1442 if (GetOpener()) {
1443 // We need to do a navigation here if the target URL has changed between
1444 // the time the WebContents was created and the time it was attached.
1445 // We also need to do an initial navigation if a RenderView was never
1446 // created for the new window in cases where there is no referrer.
1447 auto it = GetOpener()->pending_new_windows_.find(this);
1448 if (it != GetOpener()->pending_new_windows_.end()) {
1449 const NewWindowInfo& new_window_info = it->second;
1450 if (new_window_info.changed || !web_contents()->HasOpener())
1451 NavigateGuest(new_window_info.url.spec(), false /* force_navigation */);
1452
1453 // Once a new guest is attached to the DOM of the embedder page, then the
1454 // lifetime of the new guest is no longer managed by the opener guest.
1455 GetOpener()->pending_new_windows_.erase(this);
1456
1457 is_pending_new_window = true;
1458 }
1459 }
1460
1461 // Only read the src attribute if this is not a New Window API flow.
1462 if (!is_pending_new_window) {
1463 std::string src;
1464 if (params.GetString(webview::kAttributeSrc, &src))
1465 NavigateGuest(src, true /* force_navigation */);
1466 }
1491 } 1467 }
1492 1468
1493 } // namespace extensions 1469 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698