| 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
|
|
|