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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: extensions/browser/guest_view/web_view/web_view_guest.cc
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc
index f4d1cc4fe7039f12593f52c921a9ad37c2f7acb5..c3bb661d6e8663cdd31685b641057f334e735a7b 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -201,6 +201,25 @@ static base::LazyInstance<WebViewKeyToIDMap> web_view_key_to_id_map =
} // namespace
+WebViewGuest::WebViewGuest(WebContents* owner_web_contents)
+ : GuestView<WebViewGuest>(owner_web_contents),
+ rules_registry_id_(RulesRegistryService::kInvalidRulesRegistryID),
+ find_helper_(this),
+ is_overriding_user_agent_(false),
+ allow_transparency_(false),
+ javascript_dialog_helper_(this),
+ allow_scaling_(false),
+ is_guest_fullscreen_(false),
+ is_embedder_fullscreen_(false),
+ last_fullscreen_permission_was_allowed_by_embedder_(false),
+ pending_zoom_factor_(0.0),
+ weak_ptr_factory_(this) {
+ web_view_guest_delegate_.reset(
+ ExtensionsAPIClient::Get()->CreateWebViewGuestDelegate(this));
+}
+
+WebViewGuest::~WebViewGuest() {}
+
// static
void WebViewGuest::CleanUp(content::BrowserContext* browser_context,
int embedder_process_id,
@@ -303,155 +322,75 @@ int WebViewGuest::GetOrGenerateRulesRegistryID(
return rules_registry_id;
}
-bool WebViewGuest::CanRunInDetachedState() const {
- return true;
-}
-
-void WebViewGuest::CreateWebContents(
- const base::DictionaryValue& create_params,
- const WebContentsCreatedCallback& callback) {
- RenderProcessHost* owner_render_process_host =
- owner_web_contents()->GetRenderProcessHost();
- std::string storage_partition_id;
- bool persist_storage = false;
- ParsePartitionParam(create_params, &storage_partition_id, &persist_storage);
- // Validate that the partition id coming from the renderer is valid UTF-8,
- // since we depend on this in other parts of the code, such as FilePath
- // creation. If the validation fails, treat it as a bad message and kill the
- // renderer process.
- if (!base::IsStringUTF8(storage_partition_id)) {
- content::RecordAction(
- base::UserMetricsAction("BadMessageTerminate_BPGM"));
- owner_render_process_host->Shutdown(content::RESULT_CODE_KILLED_BAD_MESSAGE,
- false);
- callback.Run(nullptr);
- return;
- }
- std::string url_encoded_partition = net::EscapeQueryParamValue(
- storage_partition_id, false);
- std::string partition_domain = GetOwnerSiteURL().host();
- GURL guest_site(base::StringPrintf("%s://%s/%s?%s",
- content::kGuestScheme,
- partition_domain.c_str(),
- persist_storage ? "persist" : "",
- url_encoded_partition.c_str()));
-
- // If we already have a webview tag in the same app using the same storage
- // partition, we should use the same SiteInstance so the existing tag and
- // the new tag can script each other.
- auto guest_view_manager = GuestViewManager::FromBrowserContext(
- owner_render_process_host->GetBrowserContext());
- content::SiteInstance* guest_site_instance =
- guest_view_manager->GetGuestSiteInstance(guest_site);
- if (!guest_site_instance) {
- // Create the SiteInstance in a new BrowsingInstance, which will ensure
- // that webview tags are also not allowed to send messages across
- // different partitions.
- guest_site_instance = content::SiteInstance::CreateForURL(
- owner_render_process_host->GetBrowserContext(), guest_site);
- }
- WebContents::CreateParams params(
- owner_render_process_host->GetBrowserContext(),
- guest_site_instance);
- params.guest_delegate = this;
- callback.Run(WebContents::Create(params));
-}
-
-void WebViewGuest::DidAttachToEmbedder() {
- ApplyAttributes(*attach_params());
+double WebViewGuest::GetZoom() const {
+ double zoom_level =
+ ZoomController::FromWebContents(web_contents())->GetZoomLevel();
+ return ConvertZoomLevelToZoomFactor(zoom_level);
}
-void WebViewGuest::DidDropLink(const GURL& url) {
- scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- args->SetString(guest_view::kUrl, url.spec());
- DispatchEventToView(
- new GuestViewEvent(webview::kEventDropLink, args.Pass()));
+ZoomController::ZoomMode WebViewGuest::GetZoomMode() {
+ return ZoomController::FromWebContents(web_contents())->zoom_mode();
}
-void WebViewGuest::DidInitialize(const base::DictionaryValue& create_params) {
- script_executor_.reset(
- new ScriptExecutor(web_contents(), &script_observers_));
+void WebViewGuest::NavigateGuest(const std::string& src,
+ bool force_navigation) {
+ if (src.empty())
+ return;
- notification_registrar_.Add(this,
- content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
- content::Source<WebContents>(web_contents()));
+ GURL url = ResolveURL(src);
- notification_registrar_.Add(this,
- content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
- content::Source<WebContents>(web_contents()));
+ // We wait for all the content scripts to load and then navigate the guest
+ // if the navigation is embedder-initiated. For browser-initiated navigations,
+ // content scripts will be ready.
+ if (force_navigation) {
+ SignalWhenReady(base::Bind(
+ &WebViewGuest::LoadURLWithParams, weak_ptr_factory_.GetWeakPtr(), url,
+ content::Referrer(), ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
+ GlobalRequestID(), force_navigation));
+ return;
+ }
+ LoadURLWithParams(url, content::Referrer(), ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
+ GlobalRequestID(), force_navigation);
+}
+void WebViewGuest::ShowContextMenu(
+ int request_id,
+ const WebViewGuestDelegate::MenuItemVector* items) {
if (web_view_guest_delegate_)
- web_view_guest_delegate_->OnDidInitialize();
- ExtensionsAPIClient::Get()->AttachWebContentsHelpers(web_contents());
- web_view_permission_helper_.reset(new WebViewPermissionHelper(this));
-
- rules_registry_id_ = GetOrGenerateRulesRegistryID(
- owner_web_contents()->GetRenderProcessHost()->GetID(),
- view_instance_id());
-
- // We must install the mapping from guests to WebViews prior to resuming
- // suspended resource loads so that the WebRequest API will catch resource
- // requests.
- PushWebViewStateToIOThread();
-
- ApplyAttributes(create_params);
+ web_view_guest_delegate_->OnShowContextMenu(request_id, items);
}
-void WebViewGuest::ClearDataInternal(base::Time remove_since,
- uint32 removal_mask,
- const base::Closure& callback) {
- uint32 storage_partition_removal_mask =
- GetStoragePartitionRemovalMask(removal_mask);
- if (!storage_partition_removal_mask) {
- callback.Run();
+void WebViewGuest::SetName(const std::string& name) {
+ if (name_ == name)
return;
- }
- content::StoragePartition* partition =
- content::BrowserContext::GetStoragePartition(
- web_contents()->GetBrowserContext(),
- web_contents()->GetSiteInstance());
- partition->ClearData(
- storage_partition_removal_mask,
- content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, GURL(),
- content::StoragePartition::OriginMatcherFunction(), remove_since,
- base::Time::Now(), callback);
-}
+ name_ = name;
-void WebViewGuest::GuestViewDidStopLoading() {
- scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- DispatchEventToView(
- new GuestViewEvent(webview::kEventLoadStop, args.Pass()));
+ Send(new ExtensionMsg_SetFrameName(routing_id(), name_));
}
-void WebViewGuest::EmbedderFullscreenToggled(bool entered_fullscreen) {
- is_embedder_fullscreen_ = entered_fullscreen;
- // If the embedder has got out of fullscreen, we get out of fullscreen
- // mode as well.
- if (!entered_fullscreen)
- SetFullscreenState(false);
+void WebViewGuest::SetZoom(double zoom_factor) {
+ auto zoom_controller = ZoomController::FromWebContents(web_contents());
+ DCHECK(zoom_controller);
+ double zoom_level = content::ZoomFactorToZoomLevel(zoom_factor);
+ zoom_controller->SetZoomLevel(zoom_level);
}
-const char* WebViewGuest::GetAPINamespace() const {
- return webview::kAPINamespace;
+void WebViewGuest::SetZoomMode(ZoomController::ZoomMode zoom_mode) {
+ ZoomController::FromWebContents(web_contents())->SetZoomMode(zoom_mode);
}
-int WebViewGuest::GetTaskPrefix() const {
- return IDS_EXTENSION_TASK_MANAGER_WEBVIEW_TAG_PREFIX;
+void WebViewGuest::SetAllowScaling(bool allow) {
+ allow_scaling_ = allow;
}
-void WebViewGuest::GuestDestroyed() {
- RemoveWebViewStateFromIOThread(web_contents());
-}
+void WebViewGuest::SetAllowTransparency(bool allow) {
+ if (allow_transparency_ == allow)
+ return;
-void WebViewGuest::GuestReady() {
- // The guest RenderView should always live in an isolated guest process.
- CHECK(web_contents()->GetRenderProcessHost()->IsForGuestsOnly());
- Send(new ExtensionMsg_SetFrameName(web_contents()->GetRoutingID(), name_));
+ allow_transparency_ = allow;
+ if (!web_contents()->GetRenderViewHost()->GetView())
+ return;
- // We don't want to accidentally set the opacity of an interstitial page.
- // WebContents::GetRenderWidgetHostView will return the RWHV of an
- // interstitial page if one is showing at this time. We only want opacity
- // to apply to web pages.
if (allow_transparency_) {
web_contents()->GetRenderViewHost()->GetView()->SetBackgroundColor(
SK_ColorTRANSPARENT);
@@ -463,221 +402,59 @@ void WebViewGuest::GuestReady() {
}
}
-void WebViewGuest::GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
- const gfx::Size& new_size) {
- scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- args->SetInteger(webview::kOldHeight, old_size.height());
- args->SetInteger(webview::kOldWidth, old_size.width());
- args->SetInteger(webview::kNewHeight, new_size.height());
- args->SetInteger(webview::kNewWidth, new_size.width());
- DispatchEventToView(
- new GuestViewEvent(webview::kEventSizeChanged, args.Pass()));
-}
+bool WebViewGuest::LoadDataWithBaseURL(const std::string& data_url,
+ const std::string& base_url,
+ const std::string& virtual_url,
+ std::string* error) {
+ // Make GURLs from URLs.
+ const GURL data_gurl = GURL(data_url);
+ const GURL base_gurl = GURL(base_url);
+ const GURL virtual_gurl = GURL(virtual_url);
+
+ // Check that the provided URLs are valid.
+ // |data_url| must be a valid data URL.
+ if (!data_gurl.is_valid() || !data_gurl.SchemeIs(url::kDataScheme)) {
+ base::SStringPrintf(error, webview::kAPILoadDataInvalidDataURL,
+ data_url.c_str());
+ return false;
+ }
+ // |base_url| must be a valid URL.
+ if (!base_gurl.is_valid()) {
+ base::SStringPrintf(error, webview::kAPILoadDataInvalidBaseURL,
+ base_url.c_str());
+ return false;
+ }
+ // |virtual_url| must be a valid URL.
+ if (!virtual_gurl.is_valid()) {
+ base::SStringPrintf(error, webview::kAPILoadDataInvalidVirtualURL,
+ virtual_url.c_str());
+ return false;
+ }
+
+ // Set up the parameters to load |data_url| with the specified |base_url|.
+ content::NavigationController::LoadURLParams load_params(data_gurl);
+ load_params.load_type = content::NavigationController::LOAD_TYPE_DATA;
+ load_params.base_url_for_data_url = base_gurl;
+ load_params.virtual_url_for_data_url = virtual_gurl;
+ load_params.override_user_agent =
+ content::NavigationController::UA_OVERRIDE_INHERIT;
+
+ // Navigate to the data URL.
+ GuestViewBase::LoadURLWithParams(load_params);
-bool WebViewGuest::IsAutoSizeSupported() const {
return true;
}
-void WebViewGuest::GuestZoomChanged(double old_zoom_level,
- double new_zoom_level) {
- // Dispatch the zoomchange event.
- double old_zoom_factor = ConvertZoomLevelToZoomFactor(old_zoom_level);
- double new_zoom_factor = ConvertZoomLevelToZoomFactor(new_zoom_level);
- scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- args->SetDouble(webview::kOldZoomFactor, old_zoom_factor);
- args->SetDouble(webview::kNewZoomFactor, new_zoom_factor);
- DispatchEventToView(
- new GuestViewEvent(webview::kEventZoomChange, args.Pass()));
+void WebViewGuest::StartFindInternal(
+ const base::string16& search_text,
+ const blink::WebFindOptions& options,
+ scoped_refptr<WebViewInternalFindFunction> find_function) {
+ find_helper_.Find(web_contents(), search_text, options, find_function);
}
-void WebViewGuest::WillDestroy() {
- if (!attached() && GetOpener())
- GetOpener()->pending_new_windows_.erase(this);
-}
-
-bool WebViewGuest::AddMessageToConsole(WebContents* source,
- int32 level,
- const base::string16& message,
- int32 line_no,
- const base::string16& source_id) {
- scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- // Log levels are from base/logging.h: LogSeverity.
- args->SetInteger(webview::kLevel, level);
- args->SetString(webview::kMessage, message);
- args->SetInteger(webview::kLine, line_no);
- args->SetString(webview::kSourceId, source_id);
- DispatchEventToView(
- new GuestViewEvent(webview::kEventConsoleMessage, args.Pass()));
- return true;
-}
-
-void WebViewGuest::CloseContents(WebContents* source) {
- scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- DispatchEventToView(
- new GuestViewEvent(webview::kEventClose, args.Pass()));
-}
-
-void WebViewGuest::FindReply(WebContents* source,
- int request_id,
- int number_of_matches,
- const gfx::Rect& selection_rect,
- int active_match_ordinal,
- bool final_update) {
- GuestViewBase::FindReply(source, request_id, number_of_matches,
- selection_rect, active_match_ordinal, final_update);
- find_helper_.FindReply(request_id, number_of_matches, selection_rect,
- active_match_ordinal, final_update);
-}
-
-double WebViewGuest::GetZoom() const {
- double zoom_level =
- ZoomController::FromWebContents(web_contents())->GetZoomLevel();
- return ConvertZoomLevelToZoomFactor(zoom_level);
-}
-
-ZoomController::ZoomMode WebViewGuest::GetZoomMode() {
- return ZoomController::FromWebContents(web_contents())->zoom_mode();
-}
-
-bool WebViewGuest::HandleContextMenu(
- const content::ContextMenuParams& params) {
- if (!web_view_guest_delegate_)
- return false;
- return web_view_guest_delegate_->HandleContextMenu(params);
-}
-
-void WebViewGuest::HandleKeyboardEvent(
- WebContents* source,
- const content::NativeWebKeyboardEvent& event) {
- if (HandleKeyboardShortcuts(event))
- return;
-
- GuestViewBase::HandleKeyboardEvent(source, event);
-}
-
-bool WebViewGuest::PreHandleGestureEvent(WebContents* source,
- const blink::WebGestureEvent& event) {
- return !allow_scaling_ && GuestViewBase::PreHandleGestureEvent(source, event);
-}
-
-void WebViewGuest::LoadProgressChanged(WebContents* source, double progress) {
- scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- args->SetString(guest_view::kUrl, web_contents()->GetURL().spec());
- args->SetDouble(webview::kProgress, progress);
- DispatchEventToView(
- new GuestViewEvent(webview::kEventLoadProgress, args.Pass()));
-}
-
-void WebViewGuest::LoadAbort(bool is_top_level,
- const GURL& url,
- int error_code,
- const std::string& error_type) {
- scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- args->SetBoolean(guest_view::kIsTopLevel, is_top_level);
- args->SetString(guest_view::kUrl, url.possibly_invalid_spec());
- args->SetInteger(guest_view::kCode, error_code);
- args->SetString(guest_view::kReason, error_type);
- DispatchEventToView(
- new GuestViewEvent(webview::kEventLoadAbort, args.Pass()));
-}
-
-void WebViewGuest::SetContextMenuPosition(const gfx::Point& position) {
- if (web_view_guest_delegate_)
- web_view_guest_delegate_->SetContextMenuPosition(position);
-}
-
-void WebViewGuest::CreateNewGuestWebViewWindow(
- const content::OpenURLParams& params) {
- GuestViewManager* guest_manager =
- GuestViewManager::FromBrowserContext(browser_context());
- // Set the attach params to use the same partition as the opener.
- // We pull the partition information from the site's URL, which is of the
- // form guest://site/{persist}?{partition_name}.
- const GURL& site_url = web_contents()->GetSiteInstance()->GetSiteURL();
- const std::string storage_partition_id =
- GetStoragePartitionIdFromSiteURL(site_url);
- base::DictionaryValue create_params;
- create_params.SetString(webview::kStoragePartitionId, storage_partition_id);
-
- guest_manager->CreateGuest(WebViewGuest::Type,
- embedder_web_contents(),
- create_params,
- base::Bind(&WebViewGuest::NewGuestWebViewCallback,
- weak_ptr_factory_.GetWeakPtr(),
- params));
-}
-
-void WebViewGuest::NewGuestWebViewCallback(const content::OpenURLParams& params,
- WebContents* guest_web_contents) {
- WebViewGuest* new_guest = WebViewGuest::FromWebContents(guest_web_contents);
- new_guest->SetOpener(this);
-
- // Take ownership of |new_guest|.
- pending_new_windows_.insert(
- std::make_pair(new_guest, NewWindowInfo(params.url, std::string())));
-
- // Request permission to show the new window.
- RequestNewWindowPermission(params.disposition,
- gfx::Rect(),
- params.user_gesture,
- new_guest->web_contents());
-}
-
-// TODO(fsamuel): Find a reliable way to test the 'responsive' and
-// 'unresponsive' events.
-void WebViewGuest::RendererResponsive(WebContents* source) {
- scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- args->SetInteger(webview::kProcessId,
- web_contents()->GetRenderProcessHost()->GetID());
- DispatchEventToView(
- new GuestViewEvent(webview::kEventResponsive, args.Pass()));
-}
-
-void WebViewGuest::RendererUnresponsive(WebContents* source) {
- scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- args->SetInteger(webview::kProcessId,
- web_contents()->GetRenderProcessHost()->GetID());
- DispatchEventToView(
- new GuestViewEvent(webview::kEventUnresponsive, args.Pass()));
-}
-
-void WebViewGuest::Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- switch (type) {
- case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: {
- DCHECK_EQ(content::Source<WebContents>(source).ptr(), web_contents());
- if (content::Source<WebContents>(source).ptr() == web_contents())
- LoadHandlerCalled();
- break;
- }
- case content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: {
- DCHECK_EQ(content::Source<WebContents>(source).ptr(), web_contents());
- content::ResourceRedirectDetails* resource_redirect_details =
- content::Details<content::ResourceRedirectDetails>(details).ptr();
- bool is_top_level = resource_redirect_details->resource_type ==
- content::RESOURCE_TYPE_MAIN_FRAME;
- LoadRedirect(resource_redirect_details->url,
- resource_redirect_details->new_url,
- is_top_level);
- break;
- }
- default:
- NOTREACHED() << "Unexpected notification sent.";
- break;
- }
-}
-
-void WebViewGuest::StartFindInternal(
- const base::string16& search_text,
- const blink::WebFindOptions& options,
- scoped_refptr<WebViewInternalFindFunction> find_function) {
- find_helper_.Find(web_contents(), search_text, options, find_function);
-}
-
-void WebViewGuest::StopFindingInternal(content::StopFindAction action) {
- find_helper_.CancelAllFindSessions();
- web_contents()->StopFinding(action);
+void WebViewGuest::StopFindingInternal(content::StopFindAction action) {
+ find_helper_.CancelAllFindSessions();
+ web_contents()->StopFinding(action);
}
bool WebViewGuest::Go(int relative_index) {
@@ -756,221 +533,247 @@ bool WebViewGuest::ClearData(base::Time remove_since,
return true;
}
-WebViewGuest::WebViewGuest(WebContents* owner_web_contents)
- : GuestView<WebViewGuest>(owner_web_contents),
- rules_registry_id_(RulesRegistryService::kInvalidRulesRegistryID),
- find_helper_(this),
- is_overriding_user_agent_(false),
- allow_transparency_(false),
- javascript_dialog_helper_(this),
- allow_scaling_(false),
- is_guest_fullscreen_(false),
- is_embedder_fullscreen_(false),
- last_fullscreen_permission_was_allowed_by_embedder_(false),
- pending_zoom_factor_(0.0),
- weak_ptr_factory_(this) {
- web_view_guest_delegate_.reset(
- ExtensionsAPIClient::Get()->CreateWebViewGuestDelegate(this));
-}
-
-WebViewGuest::~WebViewGuest() {
-}
-
-void WebViewGuest::DidCommitProvisionalLoadForFrame(
- content::RenderFrameHost* render_frame_host,
- const GURL& url,
- ui::PageTransition transition_type) {
- if (!render_frame_host->GetParent()) {
- src_ = url;
- // Handle a pending zoom if one exists.
- if (pending_zoom_factor_) {
- SetZoom(pending_zoom_factor_);
- pending_zoom_factor_ = 0.0;
- }
+void WebViewGuest::ClearDataInternal(base::Time remove_since,
+ uint32 removal_mask,
+ const base::Closure& callback) {
+ uint32 storage_partition_removal_mask =
+ GetStoragePartitionRemovalMask(removal_mask);
+ if (!storage_partition_removal_mask) {
+ callback.Run();
+ return;
}
- scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- args->SetString(guest_view::kUrl, url.spec());
- args->SetBoolean(guest_view::kIsTopLevel, !render_frame_host->GetParent());
- args->SetString(webview::kInternalBaseURLForDataURL,
- web_contents()
- ->GetController()
- .GetLastCommittedEntry()
- ->GetBaseURLForDataURL()
- .spec());
- args->SetInteger(webview::kInternalCurrentEntryIndex,
- web_contents()->GetController().GetCurrentEntryIndex());
- args->SetInteger(webview::kInternalEntryCount,
- web_contents()->GetController().GetEntryCount());
- args->SetInteger(webview::kInternalProcessId,
- web_contents()->GetRenderProcessHost()->GetID());
- DispatchEventToView(
- new GuestViewEvent(webview::kEventLoadCommit, args.Pass()));
-
- find_helper_.CancelAllFindSessions();
+ content::StoragePartition* partition =
+ content::BrowserContext::GetStoragePartition(
+ web_contents()->GetBrowserContext(),
+ web_contents()->GetSiteInstance());
+ partition->ClearData(
+ storage_partition_removal_mask,
+ content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, GURL(),
+ content::StoragePartition::OriginMatcherFunction(), remove_since,
+ base::Time::Now(), callback);
}
-void WebViewGuest::DidFailProvisionalLoad(
- content::RenderFrameHost* render_frame_host,
- const GURL& validated_url,
- int error_code,
- const base::string16& error_description,
- bool was_ignored_by_handler) {
- // Suppress loadabort for "mailto" URLs.
- if (validated_url.SchemeIs(url::kMailToScheme))
+void WebViewGuest::OnWebViewNewWindowResponse(int new_window_instance_id,
+ bool allow,
+ const std::string& user_input) {
+ auto guest =
+ WebViewGuest::From(owner_web_contents()->GetRenderProcessHost()->GetID(),
+ new_window_instance_id);
+ if (!guest)
return;
- LoadAbort(!render_frame_host->GetParent(), validated_url, error_code,
- net::ErrorToShortString(error_code));
+ if (!allow)
+ guest->Destroy();
}
-void WebViewGuest::DidStartProvisionalLoadForFrame(
- content::RenderFrameHost* render_frame_host,
- const GURL& validated_url,
- bool is_error_page,
- bool is_iframe_srcdoc) {
- scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- args->SetString(guest_view::kUrl, validated_url.spec());
- args->SetBoolean(guest_view::kIsTopLevel, !render_frame_host->GetParent());
- DispatchEventToView(
- new GuestViewEvent(webview::kEventLoadStart, args.Pass()));
+void WebViewGuest::OnFullscreenPermissionDecided(
+ bool allowed,
+ const std::string& user_input) {
+ last_fullscreen_permission_was_allowed_by_embedder_ = allowed;
+ SetFullscreenState(allowed);
}
-void WebViewGuest::RenderProcessGone(base::TerminationStatus status) {
- // Cancel all find sessions in progress.
- find_helper_.CancelAllFindSessions();
-
- scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- args->SetInteger(webview::kProcessId,
- web_contents()->GetRenderProcessHost()->GetID());
- args->SetString(webview::kReason, TerminationStatusToString(status));
- DispatchEventToView(
- new GuestViewEvent(webview::kEventExit, args.Pass()));
+bool WebViewGuest::GuestMadeEmbedderFullscreen() const {
+ return last_fullscreen_permission_was_allowed_by_embedder_ &&
+ is_embedder_fullscreen_;
}
-void WebViewGuest::UserAgentOverrideSet(const std::string& user_agent) {
- content::NavigationController& controller = web_contents()->GetController();
- content::NavigationEntry* entry = controller.GetVisibleEntry();
- if (!entry)
+void WebViewGuest::SetFullscreenState(bool is_fullscreen) {
+ if (is_fullscreen == is_guest_fullscreen_)
return;
- entry->SetIsOverridingUserAgent(!user_agent.empty());
- web_contents()->GetController().Reload(false);
+
+ bool was_fullscreen = is_guest_fullscreen_;
+ is_guest_fullscreen_ = is_fullscreen;
+ // If the embedder entered fullscreen because of us, it should exit fullscreen
+ // when we exit fullscreen.
+ if (was_fullscreen && GuestMadeEmbedderFullscreen()) {
+ // Dispatch a message so we can call document.webkitCancelFullscreen()
+ // on the embedder.
+ scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
+ DispatchEventToView(
+ new GuestViewEvent(webview::kEventExitFullscreen, args.Pass()));
+ }
+ // Since we changed fullscreen state, sending a Resize message ensures that
+ // renderer/ sees the change.
+ web_contents()->GetRenderViewHost()->WasResized();
}
-void WebViewGuest::FrameNameChanged(RenderFrameHost* render_frame_host,
- const std::string& name) {
- if (render_frame_host->GetParent())
- return;
+bool WebViewGuest::CanRunInDetachedState() const {
+ return true;
+}
- if (name_ == name)
+void WebViewGuest::CreateWebContents(
+ const base::DictionaryValue& create_params,
+ const WebContentsCreatedCallback& callback) {
+ RenderProcessHost* owner_render_process_host =
+ owner_web_contents()->GetRenderProcessHost();
+ std::string storage_partition_id;
+ bool persist_storage = false;
+ ParsePartitionParam(create_params, &storage_partition_id, &persist_storage);
+ // Validate that the partition id coming from the renderer is valid UTF-8,
+ // since we depend on this in other parts of the code, such as FilePath
+ // creation. If the validation fails, treat it as a bad message and kill the
+ // renderer process.
+ if (!base::IsStringUTF8(storage_partition_id)) {
+ content::RecordAction(base::UserMetricsAction("BadMessageTerminate_BPGM"));
+ owner_render_process_host->Shutdown(content::RESULT_CODE_KILLED_BAD_MESSAGE,
+ false);
+ callback.Run(nullptr);
return;
+ }
+ std::string url_encoded_partition =
+ net::EscapeQueryParamValue(storage_partition_id, false);
+ std::string partition_domain = GetOwnerSiteURL().host();
+ GURL guest_site(base::StringPrintf(
+ "%s://%s/%s?%s", content::kGuestScheme, partition_domain.c_str(),
+ persist_storage ? "persist" : "", url_encoded_partition.c_str()));
- ReportFrameNameChange(name);
+ // If we already have a webview tag in the same app using the same storage
+ // partition, we should use the same SiteInstance so the existing tag and
+ // the new tag can script each other.
+ auto guest_view_manager = GuestViewManager::FromBrowserContext(
+ owner_render_process_host->GetBrowserContext());
+ content::SiteInstance* guest_site_instance =
+ guest_view_manager->GetGuestSiteInstance(guest_site);
+ if (!guest_site_instance) {
+ // Create the SiteInstance in a new BrowsingInstance, which will ensure
+ // that webview tags are also not allowed to send messages across
+ // different partitions.
+ guest_site_instance = content::SiteInstance::CreateForURL(
+ owner_render_process_host->GetBrowserContext(), guest_site);
+ }
+ WebContents::CreateParams params(
+ owner_render_process_host->GetBrowserContext(), guest_site_instance);
+ params.guest_delegate = this;
+ callback.Run(WebContents::Create(params));
}
-void WebViewGuest::ReportFrameNameChange(const std::string& name) {
- name_ = name;
- scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- args->SetString(webview::kName, name);
- DispatchEventToView(
- new GuestViewEvent(webview::kEventFrameNameChanged, args.Pass()));
+void WebViewGuest::DidAttachToEmbedder() {
+ ApplyAttributes(*attach_params());
}
-void WebViewGuest::LoadHandlerCalled() {
+void WebViewGuest::DidDropLink(const GURL& url) {
scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- DispatchEventToView(
- new GuestViewEvent(webview::kEventContentLoad, args.Pass()));
+ args->SetString(guest_view::kUrl, url.spec());
+ DispatchEventToView(new GuestViewEvent(webview::kEventDropLink, args.Pass()));
}
-void WebViewGuest::LoadRedirect(const GURL& old_url,
- const GURL& new_url,
- bool is_top_level) {
- scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- args->SetBoolean(guest_view::kIsTopLevel, is_top_level);
- args->SetString(webview::kNewURL, new_url.spec());
- args->SetString(webview::kOldURL, old_url.spec());
- DispatchEventToView(
- new GuestViewEvent(webview::kEventLoadRedirect, args.Pass()));
+void WebViewGuest::DidInitialize(const base::DictionaryValue& create_params) {
+ script_executor_.reset(
+ new ScriptExecutor(web_contents(), &script_observers_));
+
+ notification_registrar_.Add(this,
+ content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
+ content::Source<WebContents>(web_contents()));
+
+ notification_registrar_.Add(this,
+ content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
+ content::Source<WebContents>(web_contents()));
+
+ if (web_view_guest_delegate_)
+ web_view_guest_delegate_->OnDidInitialize();
+ ExtensionsAPIClient::Get()->AttachWebContentsHelpers(web_contents());
+ web_view_permission_helper_.reset(new WebViewPermissionHelper(this));
+
+ rules_registry_id_ = GetOrGenerateRulesRegistryID(
+ owner_web_contents()->GetRenderProcessHost()->GetID(),
+ view_instance_id());
+
+ // We must install the mapping from guests to WebViews prior to resuming
+ // suspended resource loads so that the WebRequest API will catch resource
+ // requests.
+ PushWebViewStateToIOThread();
+
+ ApplyAttributes(create_params);
}
-void WebViewGuest::PushWebViewStateToIOThread() {
- const GURL& site_url = web_contents()->GetSiteInstance()->GetSiteURL();
- std::string partition_domain;
- std::string partition_id;
- bool in_memory;
- if (!GetGuestPartitionConfigForSite(
- site_url, &partition_domain, &partition_id, &in_memory)) {
- NOTREACHED();
- return;
- }
+void WebViewGuest::EmbedderFullscreenToggled(bool entered_fullscreen) {
+ is_embedder_fullscreen_ = entered_fullscreen;
+ // If the embedder has got out of fullscreen, we get out of fullscreen
+ // mode as well.
+ if (!entered_fullscreen)
+ SetFullscreenState(false);
+}
- WebViewRendererState::WebViewInfo web_view_info;
- web_view_info.embedder_process_id =
- owner_web_contents()->GetRenderProcessHost()->GetID();
- web_view_info.instance_id = view_instance_id();
- web_view_info.partition_id = partition_id;
- web_view_info.owner_host = owner_host();
- web_view_info.rules_registry_id = rules_registry_id_;
+void WebViewGuest::FindReply(WebContents* source,
+ int request_id,
+ int number_of_matches,
+ const gfx::Rect& selection_rect,
+ int active_match_ordinal,
+ bool final_update) {
+ GuestViewBase::FindReply(source, request_id, number_of_matches,
+ selection_rect, active_match_ordinal, final_update);
+ find_helper_.FindReply(request_id, number_of_matches, selection_rect,
+ active_match_ordinal, final_update);
+}
- // Get content scripts IDs added by the guest.
- WebViewContentScriptManager* manager =
- WebViewContentScriptManager::Get(browser_context());
- DCHECK(manager);
- web_view_info.content_script_ids = manager->GetContentScriptIDSet(
- web_view_info.embedder_process_id, web_view_info.instance_id);
+const char* WebViewGuest::GetAPINamespace() const {
+ return webview::kAPINamespace;
+}
- content::BrowserThread::PostTask(
- content::BrowserThread::IO,
- FROM_HERE,
- base::Bind(&WebViewRendererState::AddGuest,
- base::Unretained(WebViewRendererState::GetInstance()),
- web_contents()->GetRenderProcessHost()->GetID(),
- web_contents()->GetRoutingID(),
- web_view_info));
+int WebViewGuest::GetTaskPrefix() const {
+ return IDS_EXTENSION_TASK_MANAGER_WEBVIEW_TAG_PREFIX;
}
-// static
-void WebViewGuest::RemoveWebViewStateFromIOThread(
- WebContents* web_contents) {
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
- base::Bind(
- &WebViewRendererState::RemoveGuest,
- base::Unretained(WebViewRendererState::GetInstance()),
- web_contents->GetRenderProcessHost()->GetID(),
- web_contents->GetRoutingID()));
+void WebViewGuest::GuestDestroyed() {
+ RemoveWebViewStateFromIOThread(web_contents());
}
-void WebViewGuest::RequestMediaAccessPermission(
- WebContents* source,
- const content::MediaStreamRequest& request,
- const content::MediaResponseCallback& callback) {
- web_view_permission_helper_->RequestMediaAccessPermission(source,
- request,
- callback);
+void WebViewGuest::GuestReady() {
+ // The guest RenderView should always live in an isolated guest process.
+ CHECK(web_contents()->GetRenderProcessHost()->IsForGuestsOnly());
+ Send(new ExtensionMsg_SetFrameName(web_contents()->GetRoutingID(), name_));
+
+ // We don't want to accidentally set the opacity of an interstitial page.
+ // WebContents::GetRenderWidgetHostView will return the RWHV of an
+ // interstitial page if one is showing at this time. We only want opacity
+ // to apply to web pages.
+ if (allow_transparency_) {
+ web_contents()->GetRenderViewHost()->GetView()->SetBackgroundColor(
+ SK_ColorTRANSPARENT);
+ } else {
+ web_contents()
+ ->GetRenderViewHost()
+ ->GetView()
+ ->SetBackgroundColorToDefault();
+ }
}
-bool WebViewGuest::CheckMediaAccessPermission(WebContents* source,
- const GURL& security_origin,
- content::MediaStreamType type) {
- return web_view_permission_helper_->CheckMediaAccessPermission(
- source, security_origin, type);
+void WebViewGuest::GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
+ const gfx::Size& new_size) {
+ scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
+ args->SetInteger(webview::kOldHeight, old_size.height());
+ args->SetInteger(webview::kOldWidth, old_size.width());
+ args->SetInteger(webview::kNewHeight, new_size.height());
+ args->SetInteger(webview::kNewWidth, new_size.width());
+ DispatchEventToView(
+ new GuestViewEvent(webview::kEventSizeChanged, args.Pass()));
}
-void WebViewGuest::CanDownload(
- const GURL& url,
- const std::string& request_method,
- const base::Callback<void(bool)>& callback) {
- web_view_permission_helper_->CanDownload(url, request_method, callback);
+void WebViewGuest::GuestViewDidStopLoading() {
+ scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
+ DispatchEventToView(new GuestViewEvent(webview::kEventLoadStop, args.Pass()));
}
-void WebViewGuest::RequestPointerLockPermission(
- bool user_gesture,
- bool last_unlocked_by_target,
- const base::Callback<void(bool)>& callback) {
- web_view_permission_helper_->RequestPointerLockPermission(
- user_gesture,
- last_unlocked_by_target,
- callback);
+void WebViewGuest::GuestZoomChanged(double old_zoom_level,
+ double new_zoom_level) {
+ // Dispatch the zoomchange event.
+ double old_zoom_factor = ConvertZoomLevelToZoomFactor(old_zoom_level);
+ double new_zoom_factor = ConvertZoomLevelToZoomFactor(new_zoom_level);
+ scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
+ args->SetDouble(webview::kOldZoomFactor, old_zoom_factor);
+ args->SetDouble(webview::kNewZoomFactor, new_zoom_factor);
+ DispatchEventToView(
+ new GuestViewEvent(webview::kEventZoomChange, args.Pass()));
+}
+
+bool WebViewGuest::IsAutoSizeSupported() const {
+ return true;
+}
+
+void WebViewGuest::SetContextMenuPosition(const gfx::Point& position) {
+ if (web_view_guest_delegate_)
+ web_view_guest_delegate_->SetContextMenuPosition(position);
}
void WebViewGuest::SignalWhenReady(const base::Closure& callback) {
@@ -995,227 +798,136 @@ void WebViewGuest::WillAttachToEmbedder() {
PushWebViewStateToIOThread();
}
-content::JavaScriptDialogManager* WebViewGuest::GetJavaScriptDialogManager(
- WebContents* source) {
- return &javascript_dialog_helper_;
+void WebViewGuest::WillDestroy() {
+ if (!attached() && GetOpener())
+ GetOpener()->pending_new_windows_.erase(this);
}
-void WebViewGuest::NavigateGuest(const std::string& src,
- bool force_navigation) {
- if (src.empty())
- return;
-
- GURL url = ResolveURL(src);
-
- // We wait for all the content scripts to load and then navigate the guest
- // if the navigation is embedder-initiated. For browser-initiated navigations,
- // content scripts will be ready.
- if (force_navigation) {
- SignalWhenReady(base::Bind(
- &WebViewGuest::LoadURLWithParams, weak_ptr_factory_.GetWeakPtr(), url,
- content::Referrer(), ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
- GlobalRequestID(), force_navigation));
- return;
+void WebViewGuest::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ switch (type) {
+ case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: {
+ DCHECK_EQ(content::Source<WebContents>(source).ptr(), web_contents());
+ if (content::Source<WebContents>(source).ptr() == web_contents())
+ LoadHandlerCalled();
+ break;
+ }
+ case content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: {
+ DCHECK_EQ(content::Source<WebContents>(source).ptr(), web_contents());
+ content::ResourceRedirectDetails* resource_redirect_details =
+ content::Details<content::ResourceRedirectDetails>(details).ptr();
+ bool is_top_level = resource_redirect_details->resource_type ==
+ content::RESOURCE_TYPE_MAIN_FRAME;
+ LoadRedirect(resource_redirect_details->url,
+ resource_redirect_details->new_url, is_top_level);
+ break;
+ }
+ default:
+ NOTREACHED() << "Unexpected notification sent.";
+ break;
}
- LoadURLWithParams(url, content::Referrer(), ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
- GlobalRequestID(), force_navigation);
}
-bool WebViewGuest::HandleKeyboardShortcuts(
- const content::NativeWebKeyboardEvent& event) {
- // <webview> outside of Chrome Apps do not handle keyboard shortcuts.
- if (!GuestViewManager::FromBrowserContext(browser_context())->
- IsOwnedByExtension(this)) {
- return false;
- }
-
- if (event.type != blink::WebInputEvent::RawKeyDown)
- return false;
-
- // If the user hits the escape key without any modifiers then unlock the
- // mouse if necessary.
- if ((event.windowsKeyCode == ui::VKEY_ESCAPE) &&
- !(event.modifiers & blink::WebInputEvent::InputModifiers)) {
- return web_contents()->GotResponseToLockMouseRequest(false);
- }
-
-#if defined(OS_MACOSX)
- if (event.modifiers != blink::WebInputEvent::MetaKey)
- return false;
-
- if (event.windowsKeyCode == ui::VKEY_OEM_4) {
- Go(-1);
- return true;
- }
-
- if (event.windowsKeyCode == ui::VKEY_OEM_6) {
- Go(1);
- return true;
- }
-#else
- if (event.windowsKeyCode == ui::VKEY_BROWSER_BACK) {
- Go(-1);
- return true;
- }
-
- if (event.windowsKeyCode == ui::VKEY_BROWSER_FORWARD) {
- Go(1);
- return true;
- }
-#endif
-
- return false;
+bool WebViewGuest::AddMessageToConsole(WebContents* source,
+ int32 level,
+ const base::string16& message,
+ int32 line_no,
+ const base::string16& source_id) {
+ scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
+ // Log levels are from base/logging.h: LogSeverity.
+ args->SetInteger(webview::kLevel, level);
+ args->SetString(webview::kMessage, message);
+ args->SetInteger(webview::kLine, line_no);
+ args->SetString(webview::kSourceId, source_id);
+ DispatchEventToView(
+ new GuestViewEvent(webview::kEventConsoleMessage, args.Pass()));
+ return true;
}
-void WebViewGuest::ApplyAttributes(const base::DictionaryValue& params) {
- std::string name;
- if (params.GetString(webview::kAttributeName, &name)) {
- // If the guest window's name is empty, then the WebView tag's name is
- // assigned. Otherwise, the guest window's name takes precedence over the
- // WebView tag's name.
- if (name_.empty())
- SetName(name);
- }
- if (attached())
- ReportFrameNameChange(name_);
-
- std::string user_agent_override;
- params.GetString(webview::kParameterUserAgentOverride, &user_agent_override);
- SetUserAgentOverride(user_agent_override);
-
- bool allow_transparency = false;
- if (params.GetBoolean(webview::kAttributeAllowTransparency,
- &allow_transparency)) {
- // We need to set the background opaque flag after navigation to ensure that
- // there is a RenderWidgetHostView available.
- SetAllowTransparency(allow_transparency);
- }
-
- bool allow_scaling = false;
- if (params.GetBoolean(webview::kAttributeAllowScaling, &allow_scaling))
- SetAllowScaling(allow_scaling);
-
- // Check for a pending zoom from before the first navigation.
- params.GetDouble(webview::kInitialZoomFactor, &pending_zoom_factor_);
-
- bool is_pending_new_window = false;
- if (GetOpener()) {
- // We need to do a navigation here if the target URL has changed between
- // the time the WebContents was created and the time it was attached.
- // We also need to do an initial navigation if a RenderView was never
- // created for the new window in cases where there is no referrer.
- auto it = GetOpener()->pending_new_windows_.find(this);
- if (it != GetOpener()->pending_new_windows_.end()) {
- const NewWindowInfo& new_window_info = it->second;
- if (new_window_info.changed || !web_contents()->HasOpener())
- NavigateGuest(new_window_info.url.spec(), false /* force_navigation */);
-
- // Once a new guest is attached to the DOM of the embedder page, then the
- // lifetime of the new guest is no longer managed by the opener guest.
- GetOpener()->pending_new_windows_.erase(this);
-
- is_pending_new_window = true;
- }
- }
-
- // Only read the src attribute if this is not a New Window API flow.
- if (!is_pending_new_window) {
- std::string src;
- if (params.GetString(webview::kAttributeSrc, &src))
- NavigateGuest(src, true /* force_navigation */);
- }
+void WebViewGuest::CloseContents(WebContents* source) {
+ scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
+ DispatchEventToView(new GuestViewEvent(webview::kEventClose, args.Pass()));
}
-void WebViewGuest::ShowContextMenu(
- int request_id,
- const WebViewGuestDelegate::MenuItemVector* items) {
- if (web_view_guest_delegate_)
- web_view_guest_delegate_->OnShowContextMenu(request_id, items);
+bool WebViewGuest::HandleContextMenu(const content::ContextMenuParams& params) {
+ if (!web_view_guest_delegate_)
+ return false;
+ return web_view_guest_delegate_->HandleContextMenu(params);
}
-void WebViewGuest::SetName(const std::string& name) {
- if (name_ == name)
+void WebViewGuest::HandleKeyboardEvent(
+ WebContents* source,
+ const content::NativeWebKeyboardEvent& event) {
+ if (HandleKeyboardShortcuts(event))
return;
- name_ = name;
- Send(new ExtensionMsg_SetFrameName(routing_id(), name_));
+ GuestViewBase::HandleKeyboardEvent(source, event);
}
-void WebViewGuest::SetZoom(double zoom_factor) {
- auto zoom_controller = ZoomController::FromWebContents(web_contents());
- DCHECK(zoom_controller);
- double zoom_level = content::ZoomFactorToZoomLevel(zoom_factor);
- zoom_controller->SetZoomLevel(zoom_level);
+void WebViewGuest::LoadProgressChanged(WebContents* source, double progress) {
+ scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
+ args->SetString(guest_view::kUrl, web_contents()->GetURL().spec());
+ args->SetDouble(webview::kProgress, progress);
+ DispatchEventToView(
+ new GuestViewEvent(webview::kEventLoadProgress, args.Pass()));
}
-void WebViewGuest::SetZoomMode(ZoomController::ZoomMode zoom_mode) {
- ZoomController::FromWebContents(web_contents())->SetZoomMode(zoom_mode);
+bool WebViewGuest::PreHandleGestureEvent(WebContents* source,
+ const blink::WebGestureEvent& event) {
+ return !allow_scaling_ && GuestViewBase::PreHandleGestureEvent(source, event);
}
-void WebViewGuest::SetAllowTransparency(bool allow) {
- if (allow_transparency_ == allow)
- return;
-
- allow_transparency_ = allow;
- if (!web_contents()->GetRenderViewHost()->GetView())
- return;
-
- if (allow_transparency_) {
- web_contents()->GetRenderViewHost()->GetView()->SetBackgroundColor(
- SK_ColorTRANSPARENT);
- } else {
- web_contents()
- ->GetRenderViewHost()
- ->GetView()
- ->SetBackgroundColorToDefault();
- }
+// TODO(fsamuel): Find a reliable way to test the 'responsive' and
+// 'unresponsive' events.
+void WebViewGuest::RendererResponsive(WebContents* source) {
+ scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
+ args->SetInteger(webview::kProcessId,
+ web_contents()->GetRenderProcessHost()->GetID());
+ DispatchEventToView(
+ new GuestViewEvent(webview::kEventResponsive, args.Pass()));
}
-void WebViewGuest::SetAllowScaling(bool allow) {
- allow_scaling_ = allow;
+void WebViewGuest::RendererUnresponsive(WebContents* source) {
+ scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
+ args->SetInteger(webview::kProcessId,
+ web_contents()->GetRenderProcessHost()->GetID());
+ DispatchEventToView(
+ new GuestViewEvent(webview::kEventUnresponsive, args.Pass()));
}
-bool WebViewGuest::LoadDataWithBaseURL(const std::string& data_url,
- const std::string& base_url,
- const std::string& virtual_url,
- std::string* error) {
- // Make GURLs from URLs.
- const GURL data_gurl = GURL(data_url);
- const GURL base_gurl = GURL(base_url);
- const GURL virtual_gurl = GURL(virtual_url);
+void WebViewGuest::RequestMediaAccessPermission(
+ WebContents* source,
+ const content::MediaStreamRequest& request,
+ const content::MediaResponseCallback& callback) {
+ web_view_permission_helper_->RequestMediaAccessPermission(source, request,
+ callback);
+}
- // Check that the provided URLs are valid.
- // |data_url| must be a valid data URL.
- if (!data_gurl.is_valid() || !data_gurl.SchemeIs(url::kDataScheme)) {
- base::SStringPrintf(
- error, webview::kAPILoadDataInvalidDataURL, data_url.c_str());
- return false;
- }
- // |base_url| must be a valid URL.
- if (!base_gurl.is_valid()) {
- base::SStringPrintf(
- error, webview::kAPILoadDataInvalidBaseURL, base_url.c_str());
- return false;
- }
- // |virtual_url| must be a valid URL.
- if (!virtual_gurl.is_valid()) {
- base::SStringPrintf(
- error, webview::kAPILoadDataInvalidVirtualURL, virtual_url.c_str());
- return false;
- }
+void WebViewGuest::RequestPointerLockPermission(
+ bool user_gesture,
+ bool last_unlocked_by_target,
+ const base::Callback<void(bool)>& callback) {
+ web_view_permission_helper_->RequestPointerLockPermission(
+ user_gesture, last_unlocked_by_target, callback);
+}
- // Set up the parameters to load |data_url| with the specified |base_url|.
- content::NavigationController::LoadURLParams load_params(data_gurl);
- load_params.load_type = content::NavigationController::LOAD_TYPE_DATA;
- load_params.base_url_for_data_url = base_gurl;
- load_params.virtual_url_for_data_url = virtual_gurl;
- load_params.override_user_agent =
- content::NavigationController::UA_OVERRIDE_INHERIT;
+bool WebViewGuest::CheckMediaAccessPermission(WebContents* source,
+ const GURL& security_origin,
+ content::MediaStreamType type) {
+ return web_view_permission_helper_->CheckMediaAccessPermission(
+ source, security_origin, type);
+}
- // Navigate to the data URL.
- GuestViewBase::LoadURLWithParams(load_params);
+void WebViewGuest::CanDownload(const GURL& url,
+ const std::string& request_method,
+ const base::Callback<void(bool)>& callback) {
+ web_view_permission_helper_->CanDownload(url, request_method, callback);
+}
- return true;
+content::JavaScriptDialogManager* WebViewGuest::GetJavaScriptDialogManager(
+ WebContents* source) {
+ return &javascript_dialog_helper_;
}
void WebViewGuest::AddNewContents(WebContents* source,
@@ -1291,53 +1003,212 @@ WebContents* WebViewGuest::OpenURLFromTab(
return web_contents();
}
- // This code path is taken if Ctrl+Click, middle click or any of the
- // keyboard/mouse combinations are used to open a link in a new tab/window.
- // This code path is also taken on client-side redirects from about:blank.
- CreateNewGuestWebViewWindow(params);
- return nullptr;
+ // This code path is taken if Ctrl+Click, middle click or any of the
+ // keyboard/mouse combinations are used to open a link in a new tab/window.
+ // This code path is also taken on client-side redirects from about:blank.
+ CreateNewGuestWebViewWindow(params);
+ return nullptr;
+}
+
+void WebViewGuest::WebContentsCreated(WebContents* source_contents,
+ int opener_render_frame_id,
+ const std::string& frame_name,
+ const GURL& target_url,
+ WebContents* new_contents) {
+ auto guest = WebViewGuest::FromWebContents(new_contents);
+ CHECK(guest);
+ guest->SetOpener(this);
+ guest->name_ = frame_name;
+ pending_new_windows_.insert(
+ std::make_pair(guest, NewWindowInfo(target_url, frame_name)));
+}
+
+void WebViewGuest::EnterFullscreenModeForTab(WebContents* web_contents,
+ const GURL& origin) {
+ // Ask the embedder for permission.
+ base::DictionaryValue request_info;
+ request_info.SetString(webview::kOrigin, origin.spec());
+ web_view_permission_helper_->RequestPermission(
+ WEB_VIEW_PERMISSION_TYPE_FULLSCREEN, request_info,
+ base::Bind(&WebViewGuest::OnFullscreenPermissionDecided,
+ weak_ptr_factory_.GetWeakPtr()),
+ false /* allowed_by_default */);
+
+ // TODO(lazyboy): Right now the guest immediately goes fullscreen within its
+ // bounds. If the embedder denies the permission then we will see a flicker.
+ // Once we have the ability to "cancel" a renderer/ fullscreen request:
+ // http://crbug.com/466854 this won't be necessary and we should be
+ // Calling SetFullscreenState(true) once the embedder allowed the request.
+ // Otherwise we would cancel renderer/ fullscreen if the embedder denied.
+ SetFullscreenState(true);
+}
+
+void WebViewGuest::ExitFullscreenModeForTab(WebContents* web_contents) {
+ SetFullscreenState(false);
+}
+
+bool WebViewGuest::IsFullscreenForTabOrPending(
+ const WebContents* web_contents) const {
+ return is_guest_fullscreen_;
+}
+
+void WebViewGuest::DidCommitProvisionalLoadForFrame(
+ content::RenderFrameHost* render_frame_host,
+ const GURL& url,
+ ui::PageTransition transition_type) {
+ if (!render_frame_host->GetParent()) {
+ src_ = url;
+ // Handle a pending zoom if one exists.
+ if (pending_zoom_factor_) {
+ SetZoom(pending_zoom_factor_);
+ pending_zoom_factor_ = 0.0;
+ }
+ }
+ scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
+ args->SetString(guest_view::kUrl, url.spec());
+ args->SetBoolean(guest_view::kIsTopLevel, !render_frame_host->GetParent());
+ args->SetString(webview::kInternalBaseURLForDataURL,
+ web_contents()
+ ->GetController()
+ .GetLastCommittedEntry()
+ ->GetBaseURLForDataURL()
+ .spec());
+ args->SetInteger(webview::kInternalCurrentEntryIndex,
+ web_contents()->GetController().GetCurrentEntryIndex());
+ args->SetInteger(webview::kInternalEntryCount,
+ web_contents()->GetController().GetEntryCount());
+ args->SetInteger(webview::kInternalProcessId,
+ web_contents()->GetRenderProcessHost()->GetID());
+ DispatchEventToView(
+ new GuestViewEvent(webview::kEventLoadCommit, args.Pass()));
+
+ find_helper_.CancelAllFindSessions();
+}
+
+void WebViewGuest::DidFailProvisionalLoad(
+ content::RenderFrameHost* render_frame_host,
+ const GURL& validated_url,
+ int error_code,
+ const base::string16& error_description,
+ bool was_ignored_by_handler) {
+ // Suppress loadabort for "mailto" URLs.
+ if (validated_url.SchemeIs(url::kMailToScheme))
+ return;
+
+ LoadAbort(!render_frame_host->GetParent(), validated_url, error_code,
+ net::ErrorToShortString(error_code));
+}
+
+void WebViewGuest::DidStartProvisionalLoadForFrame(
+ content::RenderFrameHost* render_frame_host,
+ const GURL& validated_url,
+ bool is_error_page,
+ bool is_iframe_srcdoc) {
+ scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
+ args->SetString(guest_view::kUrl, validated_url.spec());
+ args->SetBoolean(guest_view::kIsTopLevel, !render_frame_host->GetParent());
+ DispatchEventToView(
+ new GuestViewEvent(webview::kEventLoadStart, args.Pass()));
+}
+
+void WebViewGuest::RenderProcessGone(base::TerminationStatus status) {
+ // Cancel all find sessions in progress.
+ find_helper_.CancelAllFindSessions();
+
+ scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
+ args->SetInteger(webview::kProcessId,
+ web_contents()->GetRenderProcessHost()->GetID());
+ args->SetString(webview::kReason, TerminationStatusToString(status));
+ DispatchEventToView(new GuestViewEvent(webview::kEventExit, args.Pass()));
+}
+
+void WebViewGuest::UserAgentOverrideSet(const std::string& user_agent) {
+ content::NavigationController& controller = web_contents()->GetController();
+ content::NavigationEntry* entry = controller.GetVisibleEntry();
+ if (!entry)
+ return;
+ entry->SetIsOverridingUserAgent(!user_agent.empty());
+ web_contents()->GetController().Reload(false);
+}
+
+void WebViewGuest::FrameNameChanged(RenderFrameHost* render_frame_host,
+ const std::string& name) {
+ if (render_frame_host->GetParent())
+ return;
+
+ if (name_ == name)
+ return;
+
+ ReportFrameNameChange(name);
}
-void WebViewGuest::WebContentsCreated(WebContents* source_contents,
- int opener_render_frame_id,
- const std::string& frame_name,
- const GURL& target_url,
- WebContents* new_contents) {
- auto guest = WebViewGuest::FromWebContents(new_contents);
- CHECK(guest);
- guest->SetOpener(this);
- guest->name_ = frame_name;
- pending_new_windows_.insert(
- std::make_pair(guest, NewWindowInfo(target_url, frame_name)));
+void WebViewGuest::ReportFrameNameChange(const std::string& name) {
+ name_ = name;
+ scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
+ args->SetString(webview::kName, name);
+ DispatchEventToView(
+ new GuestViewEvent(webview::kEventFrameNameChanged, args.Pass()));
}
-void WebViewGuest::EnterFullscreenModeForTab(WebContents* web_contents,
- const GURL& origin) {
- // Ask the embedder for permission.
- base::DictionaryValue request_info;
- request_info.SetString(webview::kOrigin, origin.spec());
- web_view_permission_helper_->RequestPermission(
- WEB_VIEW_PERMISSION_TYPE_FULLSCREEN, request_info,
- base::Bind(&WebViewGuest::OnFullscreenPermissionDecided,
- weak_ptr_factory_.GetWeakPtr()),
- false /* allowed_by_default */);
+void WebViewGuest::LoadHandlerCalled() {
+ scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
+ DispatchEventToView(
+ new GuestViewEvent(webview::kEventContentLoad, args.Pass()));
+}
- // TODO(lazyboy): Right now the guest immediately goes fullscreen within its
- // bounds. If the embedder denies the permission then we will see a flicker.
- // Once we have the ability to "cancel" a renderer/ fullscreen request:
- // http://crbug.com/466854 this won't be necessary and we should be
- // Calling SetFullscreenState(true) once the embedder allowed the request.
- // Otherwise we would cancel renderer/ fullscreen if the embedder denied.
- SetFullscreenState(true);
+void WebViewGuest::LoadRedirect(const GURL& old_url,
+ const GURL& new_url,
+ bool is_top_level) {
+ scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
+ args->SetBoolean(guest_view::kIsTopLevel, is_top_level);
+ args->SetString(webview::kNewURL, new_url.spec());
+ args->SetString(webview::kOldURL, old_url.spec());
+ DispatchEventToView(
+ new GuestViewEvent(webview::kEventLoadRedirect, args.Pass()));
}
-void WebViewGuest::ExitFullscreenModeForTab(WebContents* web_contents) {
- SetFullscreenState(false);
+void WebViewGuest::PushWebViewStateToIOThread() {
+ const GURL& site_url = web_contents()->GetSiteInstance()->GetSiteURL();
+ std::string partition_domain;
+ std::string partition_id;
+ bool in_memory;
+ if (!GetGuestPartitionConfigForSite(site_url, &partition_domain,
+ &partition_id, &in_memory)) {
+ NOTREACHED();
+ return;
+ }
+
+ WebViewRendererState::WebViewInfo web_view_info;
+ web_view_info.embedder_process_id =
+ owner_web_contents()->GetRenderProcessHost()->GetID();
+ web_view_info.instance_id = view_instance_id();
+ web_view_info.partition_id = partition_id;
+ web_view_info.owner_host = owner_host();
+ web_view_info.rules_registry_id = rules_registry_id_;
+
+ // Get content scripts IDs added by the guest.
+ WebViewContentScriptManager* manager =
+ WebViewContentScriptManager::Get(browser_context());
+ DCHECK(manager);
+ web_view_info.content_script_ids = manager->GetContentScriptIDSet(
+ web_view_info.embedder_process_id, web_view_info.instance_id);
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&WebViewRendererState::AddGuest,
+ base::Unretained(WebViewRendererState::GetInstance()),
+ web_contents()->GetRenderProcessHost()->GetID(),
+ web_contents()->GetRoutingID(), web_view_info));
}
-bool WebViewGuest::IsFullscreenForTabOrPending(
- const WebContents* web_contents) const {
- return is_guest_fullscreen_;
+// static
+void WebViewGuest::RemoveWebViewStateFromIOThread(WebContents* web_contents) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&WebViewRendererState::RemoveGuest,
+ base::Unretained(WebViewRendererState::GetInstance()),
+ web_contents->GetRenderProcessHost()->GetID(),
+ web_contents->GetRoutingID()));
}
void WebViewGuest::LoadURLWithParams(
@@ -1444,50 +1315,155 @@ GURL WebViewGuest::ResolveURL(const std::string& src) {
return default_url.Resolve(src);
}
-void WebViewGuest::OnWebViewNewWindowResponse(
- int new_window_instance_id,
- bool allow,
- const std::string& user_input) {
- auto guest =
- WebViewGuest::From(owner_web_contents()->GetRenderProcessHost()->GetID(),
- new_window_instance_id);
- if (!guest)
- return;
+void WebViewGuest::LoadAbort(bool is_top_level,
+ const GURL& url,
+ int error_code,
+ const std::string& error_type) {
+ scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
+ args->SetBoolean(guest_view::kIsTopLevel, is_top_level);
+ args->SetString(guest_view::kUrl, url.possibly_invalid_spec());
+ args->SetInteger(guest_view::kCode, error_code);
+ args->SetString(guest_view::kReason, error_type);
+ DispatchEventToView(
+ new GuestViewEvent(webview::kEventLoadAbort, args.Pass()));
+}
- if (!allow)
- guest->Destroy();
+void WebViewGuest::CreateNewGuestWebViewWindow(
+ const content::OpenURLParams& params) {
+ GuestViewManager* guest_manager =
+ GuestViewManager::FromBrowserContext(browser_context());
+ // Set the attach params to use the same partition as the opener.
+ // We pull the partition information from the site's URL, which is of the
+ // form guest://site/{persist}?{partition_name}.
+ const GURL& site_url = web_contents()->GetSiteInstance()->GetSiteURL();
+ const std::string storage_partition_id =
+ GetStoragePartitionIdFromSiteURL(site_url);
+ base::DictionaryValue create_params;
+ create_params.SetString(webview::kStoragePartitionId, storage_partition_id);
+
+ guest_manager->CreateGuest(
+ WebViewGuest::Type, embedder_web_contents(), create_params,
+ base::Bind(&WebViewGuest::NewGuestWebViewCallback,
+ weak_ptr_factory_.GetWeakPtr(), params));
}
-void WebViewGuest::OnFullscreenPermissionDecided(
- bool allowed,
- const std::string& user_input) {
- last_fullscreen_permission_was_allowed_by_embedder_ = allowed;
- SetFullscreenState(allowed);
+void WebViewGuest::NewGuestWebViewCallback(const content::OpenURLParams& params,
+ WebContents* guest_web_contents) {
+ WebViewGuest* new_guest = WebViewGuest::FromWebContents(guest_web_contents);
+ new_guest->SetOpener(this);
+
+ // Take ownership of |new_guest|.
+ pending_new_windows_.insert(
+ std::make_pair(new_guest, NewWindowInfo(params.url, std::string())));
+
+ // Request permission to show the new window.
+ RequestNewWindowPermission(params.disposition, gfx::Rect(),
+ params.user_gesture, new_guest->web_contents());
}
-bool WebViewGuest::GuestMadeEmbedderFullscreen() const {
- return last_fullscreen_permission_was_allowed_by_embedder_ &&
- is_embedder_fullscreen_;
+bool WebViewGuest::HandleKeyboardShortcuts(
+ const content::NativeWebKeyboardEvent& event) {
+ // <webview> outside of Chrome Apps do not handle keyboard shortcuts.
+ if (!GuestViewManager::FromBrowserContext(browser_context())
+ ->IsOwnedByExtension(this)) {
+ return false;
+ }
+
+ if (event.type != blink::WebInputEvent::RawKeyDown)
+ return false;
+
+ // If the user hits the escape key without any modifiers then unlock the
+ // mouse if necessary.
+ if ((event.windowsKeyCode == ui::VKEY_ESCAPE) &&
+ !(event.modifiers & blink::WebInputEvent::InputModifiers)) {
+ return web_contents()->GotResponseToLockMouseRequest(false);
+ }
+
+#if defined(OS_MACOSX)
+ if (event.modifiers != blink::WebInputEvent::MetaKey)
+ return false;
+
+ if (event.windowsKeyCode == ui::VKEY_OEM_4) {
+ Go(-1);
+ return true;
+ }
+
+ if (event.windowsKeyCode == ui::VKEY_OEM_6) {
+ Go(1);
+ return true;
+ }
+#else
+ if (event.windowsKeyCode == ui::VKEY_BROWSER_BACK) {
+ Go(-1);
+ return true;
+ }
+
+ if (event.windowsKeyCode == ui::VKEY_BROWSER_FORWARD) {
+ Go(1);
+ return true;
+ }
+#endif
+
+ return false;
}
-void WebViewGuest::SetFullscreenState(bool is_fullscreen) {
- if (is_fullscreen == is_guest_fullscreen_)
- return;
+void WebViewGuest::ApplyAttributes(const base::DictionaryValue& params) {
+ std::string name;
+ if (params.GetString(webview::kAttributeName, &name)) {
+ // If the guest window's name is empty, then the WebView tag's name is
+ // assigned. Otherwise, the guest window's name takes precedence over the
+ // WebView tag's name.
+ if (name_.empty())
+ SetName(name);
+ }
+ if (attached())
+ ReportFrameNameChange(name_);
- bool was_fullscreen = is_guest_fullscreen_;
- is_guest_fullscreen_ = is_fullscreen;
- // If the embedder entered fullscreen because of us, it should exit fullscreen
- // when we exit fullscreen.
- if (was_fullscreen && GuestMadeEmbedderFullscreen()) {
- // Dispatch a message so we can call document.webkitCancelFullscreen()
- // on the embedder.
- scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
- DispatchEventToView(
- new GuestViewEvent(webview::kEventExitFullscreen, args.Pass()));
+ std::string user_agent_override;
+ params.GetString(webview::kParameterUserAgentOverride, &user_agent_override);
+ SetUserAgentOverride(user_agent_override);
+
+ bool allow_transparency = false;
+ if (params.GetBoolean(webview::kAttributeAllowTransparency,
+ &allow_transparency)) {
+ // We need to set the background opaque flag after navigation to ensure that
+ // there is a RenderWidgetHostView available.
+ SetAllowTransparency(allow_transparency);
+ }
+
+ bool allow_scaling = false;
+ if (params.GetBoolean(webview::kAttributeAllowScaling, &allow_scaling))
+ SetAllowScaling(allow_scaling);
+
+ // Check for a pending zoom from before the first navigation.
+ params.GetDouble(webview::kInitialZoomFactor, &pending_zoom_factor_);
+
+ bool is_pending_new_window = false;
+ if (GetOpener()) {
+ // We need to do a navigation here if the target URL has changed between
+ // the time the WebContents was created and the time it was attached.
+ // We also need to do an initial navigation if a RenderView was never
+ // created for the new window in cases where there is no referrer.
+ auto it = GetOpener()->pending_new_windows_.find(this);
+ if (it != GetOpener()->pending_new_windows_.end()) {
+ const NewWindowInfo& new_window_info = it->second;
+ if (new_window_info.changed || !web_contents()->HasOpener())
+ NavigateGuest(new_window_info.url.spec(), false /* force_navigation */);
+
+ // Once a new guest is attached to the DOM of the embedder page, then the
+ // lifetime of the new guest is no longer managed by the opener guest.
+ GetOpener()->pending_new_windows_.erase(this);
+
+ is_pending_new_window = true;
+ }
+ }
+
+ // Only read the src attribute if this is not a New Window API flow.
+ if (!is_pending_new_window) {
+ std::string src;
+ if (params.GetString(webview::kAttributeSrc, &src))
+ NavigateGuest(src, true /* force_navigation */);
}
- // Since we changed fullscreen state, sending a Resize message ensures that
- // renderer/ sees the change.
- web_contents()->GetRenderViewHost()->WasResized();
}
} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698