blob: e75b2c174cac10686b580fb193c077370e453809 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef EXTENSIONS_BROWSER_GUEST_VIEW_WEB_VIEW_WEB_VIEW_GUEST_H_
#define EXTENSIONS_BROWSER_GUEST_VIEW_WEB_VIEW_WEB_VIEW_GUEST_H_
#include <vector>
#include "base/observer_list.h"
#include "components/guest_view/browser/guest_view.h"
#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "extensions/browser/guest_view/web_view/javascript_dialog_helper.h"
#include "extensions/browser/guest_view/web_view/web_view_find_helper.h"
#include "extensions/browser/guest_view/web_view/web_view_guest_delegate.h"
#include "extensions/browser/guest_view/web_view/web_view_permission_helper.h"
#include "extensions/browser/guest_view/web_view/web_view_permission_types.h"
#include "extensions/browser/script_executor.h"
namespace blink {
struct WebFindOptions;
} // nanespace blink
namespace content {
struct GlobalRequestID;
} // namespace content
namespace extensions {
class WebViewInternalFindFunction;
// A WebViewGuest provides the browser-side implementation of the <webview> API
// and manages the dispatch of <webview> extension events. WebViewGuest is
// created on attachment. That is, when a guest WebContents is associated with
// a particular embedder WebContents. This happens on either initial navigation
// or through the use of the New Window API, when a new window is attached to
// a particular <webview>.
class WebViewGuest : public guest_view::GuestView<WebViewGuest>,
public content::NotificationObserver {
public:
// Clean up state when this GuestView is being destroyed. See
// GuestViewBase::CleanUp().
static void CleanUp(int embedder_process_id, int view_instance_id);
static GuestViewBase* Create(content::WebContents* owner_web_contents);
// For WebViewGuest, we create special guest processes, which host the
// tag content separately from the main application that embeds the tag.
// A <webview> can specify both the partition name and whether the storage
// for that partition should be persisted. Each tag gets a SiteInstance with
// a specially formatted URL, based on the application it is hosted by and
// the partition requested by it. The format for that URL is:
// chrome-guest://partition_domain/persist?partition_name
static bool GetGuestPartitionConfigForSite(const GURL& site,
std::string* partition_domain,
std::string* partition_name,
bool* in_memory);
// Returns guest_view::kInstanceIDNone if |contents| does not correspond to a
// WebViewGuest.
static int GetViewInstanceId(content::WebContents* contents);
static const char Type[];
// Returns the stored rules registry ID of the given webview. Will generate
// an ID for the first query.
static int GetOrGenerateRulesRegistryID(
int embedder_process_id,
int web_view_instance_id);
// Get the current zoom.
double GetZoom() const;
// Get the current zoom mode.
ui_zoom::ZoomController::ZoomMode GetZoomMode();
// Request navigating the guest to the provided |src| URL.
void NavigateGuest(const std::string& src, bool force_navigation);
// Shows the context menu for the guest.
// |items| acts as a filter. This restricts the current context's default
// menu items to contain only the items from |items|.
// |items| == NULL means no filtering will be applied.
void ShowContextMenu(
int request_id,
const WebViewGuestDelegate::MenuItemVector* items);
// Sets the frame name of the guest.
void SetName(const std::string& name);
// Set the zoom factor.
void SetZoom(double zoom_factor);
// Set the zoom mode.
void SetZoomMode(ui_zoom::ZoomController::ZoomMode zoom_mode);
void SetAllowScaling(bool allow);
bool allow_scaling() const { return allow_scaling_; }
// Sets the transparency of the guest.
void SetAllowTransparency(bool allow);
bool allow_transparency() const { return allow_transparency_; }
// Loads a data URL with a specified base URL and virtual URL.
bool LoadDataWithBaseURL(const std::string& data_url,
const std::string& base_url,
const std::string& virtual_url,
std::string* error);
// GuestViewBase implementation.
bool CanRunInDetachedState() const override;
void CreateWebContents(const base::DictionaryValue& create_params,
const WebContentsCreatedCallback& callback) override;
void DidAttachToEmbedder() override;
void DidDropLink(const GURL& url) override;
void DidInitialize(const base::DictionaryValue& create_params) override;
void GuestViewDidStopLoading() override;
void EmbedderFullscreenToggled(bool entered_fullscreen) override;
const char* GetAPINamespace() const override;
int GetTaskPrefix() const override;
void GuestDestroyed() override;
void GuestReady() override;
void GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
const gfx::Size& new_size) override;
void GuestZoomChanged(double old_zoom_level, double new_zoom_level) override;
bool IsAutoSizeSupported() const override;
bool IsDragAndDropEnabled() const override;
void SignalWhenReady(const base::Closure& callback) override;
void WillAttachToEmbedder() override;
void WillDestroy() override;
// WebContentsDelegate implementation.
bool AddMessageToConsole(content::WebContents* source,
int32 level,
const base::string16& message,
int32 line_no,
const base::string16& source_id) override;
void LoadProgressChanged(content::WebContents* source,
double progress) override;
void CloseContents(content::WebContents* source) override;
void FindReply(content::WebContents* source,
int request_id,
int number_of_matches,
const gfx::Rect& selection_rect,
int active_match_ordinal,
bool final_update) override;
bool HandleContextMenu(const content::ContextMenuParams& params) override;
void HandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) override;
bool PreHandleGestureEvent(content::WebContents* source,
const blink::WebGestureEvent& event) override;
void RendererResponsive(content::WebContents* source) override;
void RendererUnresponsive(content::WebContents* source) override;
void RequestMediaAccessPermission(
content::WebContents* source,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback) override;
void RequestPointerLockPermission(
bool user_gesture,
bool last_unlocked_by_target,
const base::Callback<void(bool)>& callback) override;
bool CheckMediaAccessPermission(content::WebContents* source,
const GURL& security_origin,
content::MediaStreamType type) override;
void CanDownload(const GURL& url,
const std::string& request_method,
const base::Callback<void(bool)>& callback) override;
content::JavaScriptDialogManager* GetJavaScriptDialogManager(
content::WebContents* source) override;
void AddNewContents(content::WebContents* source,
content::WebContents* new_contents,
WindowOpenDisposition disposition,
const gfx::Rect& initial_rect,
bool user_gesture,
bool* was_blocked) override;
content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) override;
void WebContentsCreated(content::WebContents* source_contents,
int opener_render_frame_id,
const base::string16& frame_name,
const GURL& target_url,
content::WebContents* new_contents) override;
void EnterFullscreenModeForTab(content::WebContents* web_contents,
const GURL& origin) override;
void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
bool IsFullscreenForTabOrPending(
const content::WebContents* web_contents) const override;
// NotificationObserver implementation.
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
// Begin or continue a find request.
void StartFindInternal(
const base::string16& search_text,
const blink::WebFindOptions& options,
scoped_refptr<WebViewInternalFindFunction> find_function);
// Conclude a find request to clear highlighting.
void StopFindingInternal(content::StopFindAction);
// If possible, navigate the guest to |relative_index| entries away from the
// current navigation entry. Returns true on success.
bool Go(int relative_index);
// Reload the guest.
void Reload();
using PermissionResponseCallback =
base::Callback<void(bool /* allow */,
const std::string& /* user_input */)>;
int RequestPermission(
WebViewPermissionType permission_type,
const base::DictionaryValue& request_info,
const PermissionResponseCallback& callback,
bool allowed_by_default);
// Requests Geolocation Permission from the embedder.
void RequestGeolocationPermission(int bridge_id,
const GURL& requesting_frame,
bool user_gesture,
const base::Callback<void(bool)>& callback);
void CancelGeolocationPermissionRequest(int bridge_id);
// Called when file system access is requested by the guest content using the
// HTML5 file system API in main thread, or a worker thread.
// The request is plumbed through the <webview> permission request API. The
// request will be:
// - Allowed if the embedder explicitly allowed it.
// - Denied if the embedder explicitly denied.
// - Determined by the guest's content settings if the embedder does not
// perform an explicit action.
void RequestFileSystemPermission(const GURL& url,
bool allowed_by_default,
const base::Callback<void(bool)>& callback);
// Overrides the user agent for this guest.
// This affects subsequent guest navigations.
void SetUserAgentOverride(const std::string& user_agent_override);
// Stop loading the guest.
void Stop();
// Kill the guest process.
void Terminate();
// Clears data in the storage partition of this guest.
//
// Partition data that are newer than |removal_since| will be removed.
// |removal_mask| corresponds to bitmask in StoragePartition::RemoveDataMask.
bool ClearData(const base::Time remove_since,
uint32 removal_mask,
const base::Closure& callback);
ScriptExecutor* script_executor() { return script_executor_.get(); }
scoped_ptr<WebViewGuestDelegate> SetDelegateForTesting(
scoped_ptr<WebViewGuestDelegate> delegate) {
web_view_guest_delegate_.swap(delegate);
return delegate.Pass();
}
private:
friend class WebViewPermissionHelper;
explicit WebViewGuest(content::WebContents* owner_web_contents);
~WebViewGuest() override;
void ClearDataInternal(const base::Time remove_since,
uint32 removal_mask,
const base::Closure& callback);
void OnWebViewNewWindowResponse(int new_window_instance_id,
bool allow,
const std::string& user_input);
void OnFullscreenPermissionDecided(bool allowed,
const std::string& user_input);
bool GuestMadeEmbedderFullscreen() const;
void SetFullscreenState(bool is_fullscreen);
// WebContentsObserver implementation.
void DidCommitProvisionalLoadForFrame(
content::RenderFrameHost* render_frame_host,
const GURL& url,
ui::PageTransition transition_type) override;
void DidFailProvisionalLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url,
int error_code,
const base::string16& error_description) override;
void DidStartProvisionalLoadForFrame(
content::RenderFrameHost* render_frame_host,
const GURL& validated_url,
bool is_error_page,
bool is_iframe_srcdoc) override;
void RenderProcessGone(base::TerminationStatus status) override;
void UserAgentOverrideSet(const std::string& user_agent) override;
void FrameNameChanged(content::RenderFrameHost* render_frame_host,
const std::string& name) override;
// Informs the embedder of a frame name change.
void ReportFrameNameChange(const std::string& name);
// Called after the load handler is called in the guest's main frame.
void LoadHandlerCalled();
// Called when a redirect notification occurs.
void LoadRedirect(const GURL& old_url,
const GURL& new_url,
bool is_top_level);
void PushWebViewStateToIOThread();
static void RemoveWebViewStateFromIOThread(
content::WebContents* web_contents);
// Loads the |url| provided. |force_navigation| indicates whether to reload
// the content if the provided |url| matches the current page of the guest.
void LoadURLWithParams(
const GURL& url,
const content::Referrer& referrer,
ui::PageTransition transition_type,
const content::GlobalRequestID& transferred_global_request_id,
bool force_navigation);
void RequestNewWindowPermission(
WindowOpenDisposition disposition,
const gfx::Rect& initial_bounds,
bool user_gesture,
content::WebContents* new_contents);
// Requests resolution of a potentially relative URL.
GURL ResolveURL(const std::string& src);
// Notification that a load in the guest resulted in abort. Note that |url|
// may be invalid.
void LoadAbort(bool is_top_level,
const GURL& url,
int error_code,
const std::string& error_type);
// Creates a new guest window owned by this WebViewGuest.
void CreateNewGuestWebViewWindow(const content::OpenURLParams& params);
void NewGuestWebViewCallback(const content::OpenURLParams& params,
content::WebContents* guest_web_contents);
bool HandleKeyboardShortcuts(const content::NativeWebKeyboardEvent& event);
void ApplyAttributes(const base::DictionaryValue& params);
// Identifies the set of rules registries belonging to this guest.
int rules_registry_id_;
// Handles find requests and replies for the webview find API.
WebViewFindHelper find_helper_;
base::ObserverList<ScriptExecutionObserver> script_observers_;
scoped_ptr<ScriptExecutor> script_executor_;
content::NotificationRegistrar notification_registrar_;
// True if the user agent is overridden.
bool is_overriding_user_agent_;
// Stores the window name of the main frame of the guest.
std::string name_;
// Stores whether the contents of the guest can be transparent.
bool allow_transparency_;
// Stores the src URL of the WebView.
GURL src_;
// Handles the JavaScript dialog requests.
JavaScriptDialogHelper javascript_dialog_helper_;
// Handles permission requests.
scoped_ptr<WebViewPermissionHelper> web_view_permission_helper_;
scoped_ptr<WebViewGuestDelegate> web_view_guest_delegate_;
// Tracks the name, and target URL of the new window. Once the first
// navigation commits, we no longer track this information.
struct NewWindowInfo {
GURL url;
std::string name;
bool changed;
NewWindowInfo(const GURL& url, const std::string& name) :
url(url),
name(name),
changed(false) {}
};
using PendingWindowMap = std::map<WebViewGuest*, NewWindowInfo>;
PendingWindowMap pending_new_windows_;
// Determines if this guest accepts pinch-zoom gestures.
bool allow_scaling_;
bool is_guest_fullscreen_;
bool is_embedder_fullscreen_;
bool last_fullscreen_permission_was_allowed_by_embedder_;
// Tracks whether the webview has a pending zoom from before the first
// navigation. This will be equal to 0 when there is no pending zoom.
double pending_zoom_factor_;
// This is used to ensure pending tasks will not fire after this object is
// destroyed.
base::WeakPtrFactory<WebViewGuest> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(WebViewGuest);
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_GUEST_VIEW_WEB_VIEW_WEB_VIEW_GUEST_H_