Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / guestview / webview / webview_guest.cc
blobd31127caeab4623b0151be62689aad9afa97fc6a
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/guestview/webview/webview_guest.h"
7 #include "base/command_line.h"
8 #include "base/strings/stringprintf.h"
9 #include "chrome/browser/extensions/api/web_request/web_request_api.h"
10 #include "chrome/browser/extensions/extension_renderer_state.h"
11 #include "chrome/browser/extensions/extension_web_contents_observer.h"
12 #include "chrome/browser/extensions/script_executor.h"
13 #include "chrome/browser/favicon/favicon_tab_helper.h"
14 #include "chrome/browser/guestview/guestview_constants.h"
15 #include "chrome/browser/guestview/webview/webview_constants.h"
16 #include "chrome/browser/guestview/webview/webview_permission_types.h"
17 #include "chrome/common/chrome_version_info.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/native_web_keyboard_event.h"
20 #include "content/public/browser/navigation_entry.h"
21 #include "content/public/browser/notification_details.h"
22 #include "content/public/browser/notification_source.h"
23 #include "content/public/browser/notification_types.h"
24 #include "content/public/browser/render_process_host.h"
25 #include "content/public/browser/resource_request_details.h"
26 #include "content/public/browser/site_instance.h"
27 #include "content/public/browser/storage_partition.h"
28 #include "content/public/browser/user_metrics.h"
29 #include "content/public/browser/web_contents.h"
30 #include "content/public/common/content_switches.h"
31 #include "content/public/common/result_codes.h"
32 #include "extensions/common/constants.h"
33 #include "net/base/net_errors.h"
35 #if defined(ENABLE_PLUGINS)
36 #include "chrome/browser/guestview/webview/plugin_permission_helper.h"
37 #endif
39 using base::UserMetricsAction;
40 using content::WebContents;
42 namespace {
44 static std::string TerminationStatusToString(base::TerminationStatus status) {
45 switch (status) {
46 case base::TERMINATION_STATUS_NORMAL_TERMINATION:
47 return "normal";
48 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
49 case base::TERMINATION_STATUS_STILL_RUNNING:
50 return "abnormal";
51 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
52 return "killed";
53 case base::TERMINATION_STATUS_PROCESS_CRASHED:
54 #if defined(OS_ANDROID)
55 case base::TERMINATION_STATUS_OOM_PROTECTED:
56 #endif
57 return "crashed";
58 case base::TERMINATION_STATUS_MAX_ENUM:
59 break;
61 NOTREACHED() << "Unknown Termination Status.";
62 return "unknown";
65 static std::string PermissionTypeToString(BrowserPluginPermissionType type) {
66 switch (type) {
67 case BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD:
68 return webview::kPermissionTypeDownload;
69 case BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION:
70 return webview::kPermissionTypeGeolocation;
71 case BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA:
72 return webview::kPermissionTypeMedia;
73 case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW:
74 return webview::kPermissionTypeNewWindow;
75 case BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK:
76 return webview::kPermissionTypePointerLock;
77 case BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
78 return webview::kPermissionTypeDialog;
79 case BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN:
80 NOTREACHED();
81 break;
82 default: {
83 WebViewPermissionType webview = static_cast<WebViewPermissionType>(type);
84 switch (webview) {
85 case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
86 return webview::kPermissionTypeLoadPlugin;
88 NOTREACHED();
91 return std::string();
94 void RemoveWebViewEventListenersOnIOThread(
95 void* profile,
96 const std::string& extension_id,
97 int embedder_process_id,
98 int view_instance_id) {
99 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
100 ExtensionWebRequestEventRouter::GetInstance()->RemoveWebViewEventListeners(
101 profile,
102 extension_id,
103 embedder_process_id,
104 view_instance_id);
107 void AttachWebViewHelpers(WebContents* contents) {
108 FaviconTabHelper::CreateForWebContents(contents);
109 extensions::ExtensionWebContentsObserver::CreateForWebContents(contents);
110 #if defined(ENABLE_PLUGINS)
111 PluginPermissionHelper::CreateForWebContents(contents);
112 #endif
115 } // namespace
117 WebViewGuest::WebViewGuest(WebContents* guest_web_contents,
118 const std::string& extension_id)
119 : GuestView(guest_web_contents, extension_id),
120 WebContentsObserver(guest_web_contents),
121 script_executor_(new extensions::ScriptExecutor(guest_web_contents,
122 &script_observers_)),
123 next_permission_request_id_(0),
124 is_overriding_user_agent_(false),
125 pending_reload_on_attachment_(false) {
126 notification_registrar_.Add(
127 this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
128 content::Source<WebContents>(guest_web_contents));
130 notification_registrar_.Add(
131 this, content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
132 content::Source<WebContents>(guest_web_contents));
134 AttachWebViewHelpers(guest_web_contents);
137 // static
138 WebViewGuest* WebViewGuest::From(int embedder_process_id,
139 int guest_instance_id) {
140 GuestView* guest = GuestView::From(embedder_process_id, guest_instance_id);
141 if (!guest)
142 return NULL;
143 return guest->AsWebView();
146 // static
147 WebViewGuest* WebViewGuest::FromWebContents(WebContents* contents) {
148 GuestView* guest = GuestView::FromWebContents(contents);
149 return guest ? guest->AsWebView() : NULL;
152 // static
153 void WebViewGuest::RecordUserInitiatedUMA(const PermissionResponseInfo& info,
154 bool allow) {
155 if (allow) {
156 // Note that |allow| == true means the embedder explicitly allowed the
157 // request. For some requests they might still fail. An example of such
158 // scenario would be: an embedder allows geolocation request but doesn't
159 // have geolocation access on its own.
160 switch (info.permission_type) {
161 case BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD:
162 content::RecordAction(
163 UserMetricsAction("BrowserPlugin.PermissionAllow.Download"));
164 break;
165 case BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION:
166 content::RecordAction(
167 UserMetricsAction("BrowserPlugin.PermissionAllow.Geolocation"));
168 break;
169 case BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA:
170 content::RecordAction(
171 UserMetricsAction("BrowserPlugin.PermissionAllow.Media"));
172 break;
173 case BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK:
174 content::RecordAction(
175 UserMetricsAction("BrowserPlugin.PermissionAllow.PointerLock"));
176 break;
177 case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW:
178 content::RecordAction(
179 UserMetricsAction("BrowserPlugin.PermissionAllow.NewWindow"));
180 break;
181 case BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
182 content::RecordAction(
183 UserMetricsAction("BrowserPlugin.PermissionAllow.JSDialog"));
184 break;
185 case BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN:
186 break;
187 default: {
188 WebViewPermissionType webview_permission_type =
189 static_cast<WebViewPermissionType>(info.permission_type);
190 switch (webview_permission_type) {
191 case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
192 content::RecordAction(
193 UserMetricsAction("WebView.Guest.PermissionAllow.PluginLoad"));
194 break;
195 default:
196 break;
200 } else {
201 switch (info.permission_type) {
202 case BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD:
203 content::RecordAction(
204 UserMetricsAction("BrowserPlugin.PermissionDeny.Download"));
205 break;
206 case BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION:
207 content::RecordAction(
208 UserMetricsAction("BrowserPlugin.PermissionDeny.Geolocation"));
209 break;
210 case BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA:
211 content::RecordAction(
212 UserMetricsAction("BrowserPlugin.PermissionDeny.Media"));
213 break;
214 case BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK:
215 content::RecordAction(
216 UserMetricsAction("BrowserPlugin.PermissionDeny.PointerLock"));
217 break;
218 case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW:
219 content::RecordAction(
220 UserMetricsAction("BrowserPlugin.PermissionDeny.NewWindow"));
221 break;
222 case BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
223 content::RecordAction(
224 UserMetricsAction("BrowserPlugin.PermissionDeny.JSDialog"));
225 break;
226 case BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN:
227 break;
228 default: {
229 WebViewPermissionType webview_permission_type =
230 static_cast<WebViewPermissionType>(info.permission_type);
231 switch (webview_permission_type) {
232 case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
233 content::RecordAction(
234 UserMetricsAction("WebView.Guest.PermissionDeny.PluginLoad"));
235 break;
236 default:
237 break;
244 void WebViewGuest::Attach(WebContents* embedder_web_contents,
245 const base::DictionaryValue& args) {
246 std::string user_agent_override;
247 if (args.GetString(webview::kParameterUserAgentOverride,
248 &user_agent_override)) {
249 SetUserAgentOverride(user_agent_override);
250 } else {
251 SetUserAgentOverride("");
254 GuestView::Attach(embedder_web_contents, args);
256 AddWebViewToExtensionRendererState();
259 GuestView::Type WebViewGuest::GetViewType() const {
260 return GuestView::WEBVIEW;
263 WebViewGuest* WebViewGuest::AsWebView() {
264 return this;
267 AdViewGuest* WebViewGuest::AsAdView() {
268 return NULL;
271 void WebViewGuest::AddMessageToConsole(int32 level,
272 const base::string16& message,
273 int32 line_no,
274 const base::string16& source_id) {
275 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
276 // Log levels are from base/logging.h: LogSeverity.
277 args->SetInteger(webview::kLevel, level);
278 args->SetString(webview::kMessage, message);
279 args->SetInteger(webview::kLine, line_no);
280 args->SetString(webview::kSourceId, source_id);
281 DispatchEvent(
282 new GuestView::Event(webview::kEventConsoleMessage, args.Pass()));
285 void WebViewGuest::Close() {
286 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
287 DispatchEvent(new GuestView::Event(webview::kEventClose, args.Pass()));
290 void WebViewGuest::DidAttach() {
291 if (pending_reload_on_attachment_) {
292 pending_reload_on_attachment_ = false;
293 guest_web_contents()->GetController().Reload(false);
297 void WebViewGuest::EmbedderDestroyed() {
298 // TODO(fsamuel): WebRequest event listeners for <webview> should survive
299 // reparenting of a <webview> within a single embedder. Right now, we keep
300 // around the browser state for the listener for the lifetime of the embedder.
301 // Ideally, the lifetime of the listeners should match the lifetime of the
302 // <webview> DOM node. Once http://crbug.com/156219 is resolved we can move
303 // the call to RemoveWebViewEventListenersOnIOThread back to
304 // WebViewGuest::WebContentsDestroyed.
305 content::BrowserThread::PostTask(
306 content::BrowserThread::IO,
307 FROM_HERE,
308 base::Bind(
309 &RemoveWebViewEventListenersOnIOThread,
310 browser_context(), extension_id(),
311 embedder_render_process_id(),
312 view_instance_id()));
315 void WebViewGuest::GuestProcessGone(base::TerminationStatus status) {
316 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
317 args->SetInteger(webview::kProcessId,
318 web_contents()->GetRenderProcessHost()->GetID());
319 args->SetString(webview::kReason, TerminationStatusToString(status));
320 DispatchEvent(
321 new GuestView::Event(webview::kEventExit, args.Pass()));
324 bool WebViewGuest::HandleKeyboardEvent(
325 const content::NativeWebKeyboardEvent& event) {
326 if (event.type != blink::WebInputEvent::RawKeyDown)
327 return false;
329 #if defined(OS_MACOSX)
330 if (event.modifiers != blink::WebInputEvent::MetaKey)
331 return false;
333 if (event.windowsKeyCode == ui::VKEY_OEM_4) {
334 Go(-1);
335 return true;
338 if (event.windowsKeyCode == ui::VKEY_OEM_6) {
339 Go(1);
340 return true;
342 #else
343 if (event.windowsKeyCode == ui::VKEY_BROWSER_BACK) {
344 Go(-1);
345 return true;
348 if (event.windowsKeyCode == ui::VKEY_BROWSER_FORWARD) {
349 Go(1);
350 return true;
352 #endif
353 return false;
356 bool WebViewGuest::IsDragAndDropEnabled() {
357 #if defined(OS_CHROMEOS)
358 return true;
359 #else
360 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
361 if (channel != chrome::VersionInfo::CHANNEL_STABLE &&
362 channel != chrome::VersionInfo::CHANNEL_BETA) {
363 // Drag and drop is enabled in canary and dev channel.
364 return true;
367 return CommandLine::ForCurrentProcess()->HasSwitch(
368 switches::kEnableBrowserPluginDragDrop);
369 #endif
372 bool WebViewGuest::IsOverridingUserAgent() const {
373 return is_overriding_user_agent_;
376 void WebViewGuest::LoadProgressed(double progress) {
377 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
378 args->SetString(guestview::kUrl, web_contents()->GetURL().spec());
379 args->SetDouble(webview::kProgress, progress);
380 DispatchEvent(new GuestView::Event(webview::kEventLoadProgress, args.Pass()));
383 void WebViewGuest::LoadAbort(bool is_top_level,
384 const GURL& url,
385 const std::string& error_type) {
386 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
387 args->SetBoolean(guestview::kIsTopLevel, is_top_level);
388 args->SetString(guestview::kUrl, url.possibly_invalid_spec());
389 args->SetString(guestview::kReason, error_type);
390 DispatchEvent(new GuestView::Event(webview::kEventLoadAbort, args.Pass()));
393 // TODO(fsamuel): Find a reliable way to test the 'responsive' and
394 // 'unresponsive' events.
395 void WebViewGuest::RendererResponsive() {
396 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
397 args->SetInteger(webview::kProcessId,
398 guest_web_contents()->GetRenderProcessHost()->GetID());
399 DispatchEvent(new GuestView::Event(webview::kEventResponsive, args.Pass()));
402 void WebViewGuest::RendererUnresponsive() {
403 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
404 args->SetInteger(webview::kProcessId,
405 guest_web_contents()->GetRenderProcessHost()->GetID());
406 DispatchEvent(new GuestView::Event(webview::kEventUnresponsive, args.Pass()));
409 bool WebViewGuest::RequestPermission(
410 BrowserPluginPermissionType permission_type,
411 const base::DictionaryValue& request_info,
412 const PermissionResponseCallback& callback,
413 bool allowed_by_default) {
414 // If there are too many pending permission requests then reject this request.
415 if (pending_permission_requests_.size() >=
416 webview::kMaxOutstandingPermissionRequests) {
417 callback.Run(false, std::string());
418 return true;
421 int request_id = next_permission_request_id_++;
422 pending_permission_requests_[request_id] =
423 PermissionResponseInfo(callback, permission_type, allowed_by_default);
424 scoped_ptr<base::DictionaryValue> args(request_info.DeepCopy());
425 args->SetInteger(webview::kRequestId, request_id);
426 switch (permission_type) {
427 case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW: {
428 DispatchEvent(new GuestView::Event(webview::kEventNewWindow,
429 args.Pass()));
430 break;
432 case BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG: {
433 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
434 if (channel > chrome::VersionInfo::CHANNEL_DEV) {
435 // 'dialog' API is not available in stable/beta.
436 callback.Run(false, std::string());
437 return true;
439 DispatchEvent(new GuestView::Event(webview::kEventDialog,
440 args.Pass()));
441 break;
443 default: {
444 args->SetString(webview::kPermission,
445 PermissionTypeToString(permission_type));
446 DispatchEvent(new GuestView::Event(webview::kEventPermissionRequest,
447 args.Pass()));
448 break;
451 return true;
454 void WebViewGuest::Observe(int type,
455 const content::NotificationSource& source,
456 const content::NotificationDetails& details) {
457 switch (type) {
458 case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: {
459 DCHECK_EQ(content::Source<WebContents>(source).ptr(),
460 guest_web_contents());
461 if (content::Source<WebContents>(source).ptr() == guest_web_contents())
462 LoadHandlerCalled();
463 break;
465 case content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: {
466 DCHECK_EQ(content::Source<WebContents>(source).ptr(),
467 guest_web_contents());
468 content::ResourceRedirectDetails* resource_redirect_details =
469 content::Details<content::ResourceRedirectDetails>(details).ptr();
470 bool is_top_level =
471 resource_redirect_details->resource_type == ResourceType::MAIN_FRAME;
472 LoadRedirect(resource_redirect_details->url,
473 resource_redirect_details->new_url,
474 is_top_level);
475 break;
477 default:
478 NOTREACHED() << "Unexpected notification sent.";
479 break;
483 void WebViewGuest::Go(int relative_index) {
484 guest_web_contents()->GetController().GoToOffset(relative_index);
487 void WebViewGuest::Reload() {
488 // TODO(fsamuel): Don't check for repost because we don't want to show
489 // Chromium's repost warning. We might want to implement a separate API
490 // for registering a callback if a repost is about to happen.
491 guest_web_contents()->GetController().Reload(false);
494 WebViewGuest::SetPermissionResult WebViewGuest::SetPermission(
495 int request_id,
496 PermissionResponseAction action,
497 const std::string& user_input) {
498 RequestMap::iterator request_itr =
499 pending_permission_requests_.find(request_id);
501 if (request_itr == pending_permission_requests_.end())
502 return SET_PERMISSION_INVALID;
504 const PermissionResponseInfo& info = request_itr->second;
505 bool allow = (action == ALLOW) ||
506 ((action == DEFAULT) && info.allowed_by_default);
508 info.callback.Run(allow, user_input);
510 // Only record user initiated (i.e. non-default) actions.
511 if (action != DEFAULT)
512 RecordUserInitiatedUMA(info, allow);
514 pending_permission_requests_.erase(request_itr);
516 return allow ? SET_PERMISSION_ALLOWED : SET_PERMISSION_DENIED;
519 void WebViewGuest::SetUserAgentOverride(
520 const std::string& user_agent_override) {
521 is_overriding_user_agent_ = !user_agent_override.empty();
522 if (is_overriding_user_agent_) {
523 content::RecordAction(UserMetricsAction("WebView.Guest.OverrideUA"));
525 guest_web_contents()->SetUserAgentOverride(user_agent_override);
528 void WebViewGuest::Stop() {
529 guest_web_contents()->Stop();
532 void WebViewGuest::Terminate() {
533 content::RecordAction(UserMetricsAction("WebView.Guest.Terminate"));
534 base::ProcessHandle process_handle =
535 guest_web_contents()->GetRenderProcessHost()->GetHandle();
536 if (process_handle)
537 base::KillProcess(process_handle, content::RESULT_CODE_KILLED, false);
540 bool WebViewGuest::ClearData(const base::Time remove_since,
541 uint32 removal_mask,
542 const base::Closure& callback) {
543 content::RecordAction(UserMetricsAction("WebView.Guest.ClearData"));
544 content::StoragePartition* partition =
545 content::BrowserContext::GetStoragePartition(
546 web_contents()->GetBrowserContext(),
547 web_contents()->GetSiteInstance());
549 if (!partition)
550 return false;
552 partition->ClearData(
553 removal_mask,
554 content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
555 GURL(),
556 content::StoragePartition::OriginMatcherFunction(),
557 remove_since,
558 base::Time::Now(),
559 callback);
560 return true;
563 WebViewGuest::~WebViewGuest() {
566 void WebViewGuest::DidCommitProvisionalLoadForFrame(
567 int64 frame_id,
568 const base::string16& frame_unique_name,
569 bool is_main_frame,
570 const GURL& url,
571 content::PageTransition transition_type,
572 content::RenderViewHost* render_view_host) {
573 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
574 args->SetString(guestview::kUrl, url.spec());
575 args->SetBoolean(guestview::kIsTopLevel, is_main_frame);
576 args->SetInteger(webview::kInternalCurrentEntryIndex,
577 web_contents()->GetController().GetCurrentEntryIndex());
578 args->SetInteger(webview::kInternalEntryCount,
579 web_contents()->GetController().GetEntryCount());
580 args->SetInteger(webview::kInternalProcessId,
581 web_contents()->GetRenderProcessHost()->GetID());
582 DispatchEvent(new GuestView::Event(webview::kEventLoadCommit, args.Pass()));
585 void WebViewGuest::DidFailProvisionalLoad(
586 int64 frame_id,
587 const base::string16& frame_unique_name,
588 bool is_main_frame,
589 const GURL& validated_url,
590 int error_code,
591 const base::string16& error_description,
592 content::RenderViewHost* render_view_host) {
593 // Translate the |error_code| into an error string.
594 std::string error_type;
595 base::RemoveChars(net::ErrorToString(error_code), "net::", &error_type);
596 LoadAbort(is_main_frame, validated_url, error_type);
599 void WebViewGuest::DidStartProvisionalLoadForFrame(
600 int64 frame_id,
601 int64 parent_frame_id,
602 bool is_main_frame,
603 const GURL& validated_url,
604 bool is_error_page,
605 bool is_iframe_srcdoc,
606 content::RenderViewHost* render_view_host) {
607 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
608 args->SetString(guestview::kUrl, validated_url.spec());
609 args->SetBoolean(guestview::kIsTopLevel, is_main_frame);
610 DispatchEvent(new GuestView::Event(webview::kEventLoadStart, args.Pass()));
613 void WebViewGuest::DidStopLoading(content::RenderViewHost* render_view_host) {
614 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
615 DispatchEvent(new GuestView::Event(webview::kEventLoadStop, args.Pass()));
618 void WebViewGuest::WebContentsDestroyed(WebContents* web_contents) {
619 RemoveWebViewFromExtensionRendererState(web_contents);
622 void WebViewGuest::UserAgentOverrideSet(const std::string& user_agent) {
623 content::NavigationController& controller =
624 guest_web_contents()->GetController();
625 content::NavigationEntry* entry = controller.GetVisibleEntry();
626 if (!entry)
627 return;
628 entry->SetIsOverridingUserAgent(!user_agent.empty());
629 if (!attached()) {
630 // We cannot reload now because all resource loads are suspended until
631 // attachment.
632 pending_reload_on_attachment_ = true;
633 return;
635 guest_web_contents()->GetController().Reload(false);
638 void WebViewGuest::LoadHandlerCalled() {
639 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
640 DispatchEvent(new GuestView::Event(webview::kEventContentLoad, args.Pass()));
643 void WebViewGuest::LoadRedirect(const GURL& old_url,
644 const GURL& new_url,
645 bool is_top_level) {
646 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
647 args->SetBoolean(guestview::kIsTopLevel, is_top_level);
648 args->SetString(webview::kNewURL, new_url.spec());
649 args->SetString(webview::kOldURL, old_url.spec());
650 DispatchEvent(new GuestView::Event(webview::kEventLoadRedirect, args.Pass()));
653 // static
654 bool WebViewGuest::AllowChromeExtensionURLs() {
655 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
656 return channel <= chrome::VersionInfo::CHANNEL_DEV;
659 void WebViewGuest::AddWebViewToExtensionRendererState() {
660 const GURL& site_url = web_contents()->GetSiteInstance()->GetSiteURL();
661 std::string partition_domain;
662 std::string partition_id;
663 bool in_memory;
664 if (!GetGuestPartitionConfigForSite(
665 site_url, &partition_domain, &partition_id, &in_memory)) {
666 NOTREACHED();
667 return;
669 DCHECK(extension_id() == partition_domain);
671 ExtensionRendererState::WebViewInfo webview_info;
672 webview_info.embedder_process_id = embedder_render_process_id();
673 webview_info.instance_id = view_instance_id();
674 webview_info.partition_id = partition_id;
675 webview_info.extension_id = extension_id();
676 webview_info.allow_chrome_extension_urls = AllowChromeExtensionURLs();
678 content::BrowserThread::PostTask(
679 content::BrowserThread::IO, FROM_HERE,
680 base::Bind(
681 &ExtensionRendererState::AddWebView,
682 base::Unretained(ExtensionRendererState::GetInstance()),
683 guest_web_contents()->GetRenderProcessHost()->GetID(),
684 guest_web_contents()->GetRoutingID(),
685 webview_info));
688 // static
689 void WebViewGuest::RemoveWebViewFromExtensionRendererState(
690 WebContents* web_contents) {
691 content::BrowserThread::PostTask(
692 content::BrowserThread::IO, FROM_HERE,
693 base::Bind(
694 &ExtensionRendererState::RemoveWebView,
695 base::Unretained(ExtensionRendererState::GetInstance()),
696 web_contents->GetRenderProcessHost()->GetID(),
697 web_contents->GetRoutingID()));
700 GURL WebViewGuest::ResolveURL(const std::string& src) {
701 if (extension_id().empty()) {
702 NOTREACHED();
703 return GURL(src);
706 // Only resolve URL to chrome-extension:// if we support such URLs.
707 if (!AllowChromeExtensionURLs())
708 return GURL(src);
710 GURL default_url(base::StringPrintf("%s://%s/",
711 extensions::kExtensionScheme,
712 extension_id().c_str()));
713 return default_url.Resolve(src);
716 void WebViewGuest::SizeChanged(const gfx::Size& old_size,
717 const gfx::Size& new_size) {
718 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
719 args->SetInteger(webview::kOldHeight, old_size.height());
720 args->SetInteger(webview::kOldWidth, old_size.width());
721 args->SetInteger(webview::kNewHeight, new_size.height());
722 args->SetInteger(webview::kNewWidth, new_size.width());
723 DispatchEvent(new GuestView::Event(webview::kEventSizeChanged, args.Pass()));
726 WebViewGuest::PermissionResponseInfo::PermissionResponseInfo()
727 : permission_type(BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN),
728 allowed_by_default(false) {
731 WebViewGuest::PermissionResponseInfo::PermissionResponseInfo(
732 const PermissionResponseCallback& callback,
733 BrowserPluginPermissionType permission_type,
734 bool allowed_by_default)
735 : callback(callback),
736 permission_type(permission_type),
737 allowed_by_default(allowed_by_default) {
740 WebViewGuest::PermissionResponseInfo::~PermissionResponseInfo() {