1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CHROME_BROWSER_GUEST_VIEW_WEB_VIEW_WEB_VIEW_GUEST_H_
6 #define CHROME_BROWSER_GUEST_VIEW_WEB_VIEW_WEB_VIEW_GUEST_H_
10 #include "base/observer_list.h"
11 #include "chrome/browser/extensions/tab_helper.h"
12 #include "chrome/browser/guest_view/guest_view.h"
13 #include "chrome/browser/guest_view/web_view/javascript_dialog_helper.h"
14 #include "chrome/browser/guest_view/web_view/web_view_find_helper.h"
15 #include "chrome/common/extensions/api/webview.h"
16 #include "content/public/browser/javascript_dialog_manager.h"
17 #include "content/public/browser/notification_registrar.h"
18 #include "content/public/browser/web_contents_observer.h"
19 #include "third_party/WebKit/public/web/WebFindOptions.h"
21 #if defined(OS_CHROMEOS)
22 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
25 namespace webview_api = extensions::api::webview;
27 class RenderViewContextMenu;
29 namespace extensions {
31 class WebviewFindFunction;
32 } // namespace extensions
35 class SimpleMenuModel;
38 // A WebViewGuest is a WebContentsObserver on the guest WebContents of a
39 // <webview> tag. It provides the browser-side implementation of the <webview>
40 // API and manages the lifetime of <webview> extension events. WebViewGuest is
41 // created on attachment. That is, when a guest WebContents is associated with
42 // a particular embedder WebContents. This happens on either initial navigation
43 // or through the use of the New Window API, when a new window is attached to
44 // a particular <webview>.
45 class WebViewGuest : public GuestView<WebViewGuest>,
46 public content::NotificationObserver,
47 public content::WebContentsObserver {
49 WebViewGuest(content::WebContents* guest_web_contents,
50 const std::string& embedder_extension_id,
51 const base::WeakPtr<GuestViewBase>& opener);
53 // Returns guestview::kInstanceIDNone if |contents| does not correspond to a
55 static int GetViewInstanceId(content::WebContents* contents);
56 static const char Type[];
58 typedef std::vector<linked_ptr<webview_api::ContextMenuItem> > MenuItemVector;
59 // Shows the context menu for the guest.
60 // |items| acts as a filter. This restricts the current context's default
61 // menu items to contain only the items from |items|.
62 // |items| == NULL means no filtering will be applied.
63 void ShowContextMenu(int request_id, const MenuItemVector* items);
65 // GuestViewBase implementation.
66 virtual void Attach(content::WebContents* embedder_web_contents,
67 const base::DictionaryValue& args) OVERRIDE;
69 // BrowserPluginGuestDelegate public implementation.
70 virtual bool HandleContextMenu(
71 const content::ContextMenuParams& params) OVERRIDE;
73 // GuestDelegate implementation.
74 virtual void AddMessageToConsole(int32 level,
75 const base::string16& message,
77 const base::string16& source_id) OVERRIDE;
78 virtual void LoadProgressed(double progress) OVERRIDE;
79 virtual void Close() OVERRIDE;
80 virtual void DidAttach() OVERRIDE;
81 virtual void EmbedderDestroyed() OVERRIDE;
82 virtual void FindReply(int request_id,
83 int number_of_matches,
84 const gfx::Rect& selection_rect,
85 int active_match_ordinal,
86 bool final_update) OVERRIDE;
87 virtual void GuestProcessGone(base::TerminationStatus status) OVERRIDE;
88 virtual bool HandleKeyboardEvent(
89 const content::NativeWebKeyboardEvent& event) OVERRIDE;
90 virtual bool IsDragAndDropEnabled() OVERRIDE;
91 virtual bool IsOverridingUserAgent() const OVERRIDE;
92 virtual void LoadAbort(bool is_top_level,
94 const std::string& error_type) OVERRIDE;
95 virtual void RendererResponsive() OVERRIDE;
96 virtual void RendererUnresponsive() OVERRIDE;
97 virtual void RequestPermission(
98 BrowserPluginPermissionType permission_type,
99 const base::DictionaryValue& request_info,
100 const PermissionResponseCallback& callback,
101 bool allowed_by_default) OVERRIDE;
102 virtual GURL ResolveURL(const std::string& src) OVERRIDE;
103 virtual void SizeChanged(const gfx::Size& old_size, const gfx::Size& new_size)
105 virtual void RequestMediaAccessPermission(
106 const content::MediaStreamRequest& request,
107 const content::MediaResponseCallback& callback) OVERRIDE;
108 virtual void CanDownload(const std::string& request_method,
110 const base::Callback<void(bool)>& callback) OVERRIDE;
111 virtual void RequestPointerLockPermission(
113 bool last_unlocked_by_target,
114 const base::Callback<void(bool)>& callback) OVERRIDE;
115 virtual content::JavaScriptDialogManager*
116 GetJavaScriptDialogManager() OVERRIDE;
118 // NotificationObserver implementation.
119 virtual void Observe(int type,
120 const content::NotificationSource& source,
121 const content::NotificationDetails& details) OVERRIDE;
123 // Set the zoom factor.
124 virtual void SetZoom(double zoom_factor) OVERRIDE;
126 // Returns the current zoom factor.
129 // Begin or continue a find request.
130 void Find(const base::string16& search_text,
131 const blink::WebFindOptions& options,
132 scoped_refptr<extensions::WebviewFindFunction> find_function);
134 // Conclude a find request to clear highlighting.
135 void StopFinding(content::StopFindAction);
137 // If possible, navigate the guest to |relative_index| entries away from the
138 // current navigation entry.
139 void Go(int relative_index);
144 // Requests Geolocation Permission from the embedder.
145 void RequestGeolocationPermission(int bridge_id,
146 const GURL& requesting_frame,
148 const base::Callback<void(bool)>& callback);
150 void OnWebViewGeolocationPermissionResponse(
153 const base::Callback<void(bool)>& callback,
155 const std::string& user_input);
157 void CancelGeolocationPermissionRequest(int bridge_id);
159 void OnWebViewMediaPermissionResponse(
160 const content::MediaStreamRequest& request,
161 const content::MediaResponseCallback& callback,
163 const std::string& user_input);
165 void OnWebViewDownloadPermissionResponse(
166 const base::Callback<void(bool)>& callback,
168 const std::string& user_input);
170 void OnWebViewPointerLockPermissionResponse(
171 const base::Callback<void(bool)>& callback,
173 const std::string& user_input);
175 enum PermissionResponseAction {
181 enum SetPermissionResult {
182 SET_PERMISSION_INVALID,
183 SET_PERMISSION_ALLOWED,
184 SET_PERMISSION_DENIED
187 // Responds to the permission request |request_id| with |action| and
188 // |user_input|. Returns whether there was a pending request for the provided
190 SetPermissionResult SetPermission(int request_id,
191 PermissionResponseAction action,
192 const std::string& user_input);
194 // Overrides the user agent for this guest.
195 // This affects subsequent guest navigations.
196 void SetUserAgentOverride(const std::string& user_agent_override);
198 // Stop loading the guest.
201 // Kill the guest process.
204 // Clears data in the storage partition of this guest.
206 // Partition data that are newer than |removal_since| will be removed.
207 // |removal_mask| corresponds to bitmask in StoragePartition::RemoveDataMask.
208 bool ClearData(const base::Time remove_since,
210 const base::Closure& callback);
212 extensions::ScriptExecutor* script_executor() {
213 return script_executor_.get();
217 virtual ~WebViewGuest();
219 // A map to store the callback for a request keyed by the request's id.
220 struct PermissionResponseInfo {
221 PermissionResponseCallback callback;
222 BrowserPluginPermissionType permission_type;
223 bool allowed_by_default;
224 PermissionResponseInfo();
225 PermissionResponseInfo(const PermissionResponseCallback& callback,
226 BrowserPluginPermissionType permission_type,
227 bool allowed_by_default);
228 ~PermissionResponseInfo();
231 static void RecordUserInitiatedUMA(const PermissionResponseInfo& info,
234 // Returns the top level items (ignoring submenus) as Value.
235 static scoped_ptr<base::ListValue> MenuModelToValue(
236 const ui::SimpleMenuModel& menu_model);
238 // WebContentsObserver implementation.
239 virtual void DidCommitProvisionalLoadForFrame(
241 const base::string16& frame_unique_name,
244 content::PageTransition transition_type,
245 content::RenderViewHost* render_view_host) OVERRIDE;
246 virtual void DidFailProvisionalLoad(
248 const base::string16& frame_unique_name,
250 const GURL& validated_url,
252 const base::string16& error_description,
253 content::RenderViewHost* render_view_host) OVERRIDE;
254 virtual void DidStartProvisionalLoadForFrame(
256 int64 parent_frame_id,
258 const GURL& validated_url,
260 bool is_iframe_srcdoc,
261 content::RenderViewHost* render_view_host) OVERRIDE;
262 virtual void DocumentLoadedInFrame(
264 content::RenderViewHost* render_view_host) OVERRIDE;
265 virtual void DidStopLoading(
266 content::RenderViewHost* render_view_host) OVERRIDE;
267 virtual void WebContentsDestroyed() OVERRIDE;
268 virtual void UserAgentOverrideSet(const std::string& user_agent) OVERRIDE;
270 // Called after the load handler is called in the guest's main frame.
271 void LoadHandlerCalled();
273 // Called when a redirect notification occurs.
274 void LoadRedirect(const GURL& old_url,
278 void AddWebViewToExtensionRendererState();
279 static void RemoveWebViewFromExtensionRendererState(
280 content::WebContents* web_contents);
282 #if defined(OS_CHROMEOS)
283 // Notification of a change in the state of an accessibility setting.
284 void OnAccessibilityStatusChanged(
285 const chromeos::AccessibilityStatusEventDetails& details);
288 void InjectChromeVoxIfNeeded(content::RenderViewHost* render_view_host);
290 // Bridge IDs correspond to a geolocation request. This method will remove
291 // the bookkeeping for a particular geolocation request associated with the
292 // provided |bridge_id|. It returns the request ID of the geolocation request.
293 int RemoveBridgeID(int bridge_id);
295 int RequestPermissionInternal(
296 BrowserPluginPermissionType permission_type,
297 const base::DictionaryValue& request_info,
298 const PermissionResponseCallback& callback,
299 bool allowed_by_default);
301 ObserverList<extensions::TabHelper::ScriptExecutionObserver>
303 scoped_ptr<extensions::ScriptExecutor> script_executor_;
305 content::NotificationRegistrar notification_registrar_;
307 // A counter to generate a unique request id for a context menu request.
308 // We only need the ids to be unique for a given WebViewGuest.
309 int pending_context_menu_request_id_;
311 // A counter to generate a unique request id for a permission request.
312 // We only need the ids to be unique for a given WebViewGuest.
313 int next_permission_request_id_;
315 typedef std::map<int, PermissionResponseInfo> RequestMap;
316 RequestMap pending_permission_requests_;
318 // True if the user agent is overridden.
319 bool is_overriding_user_agent_;
321 // Indicates that the page needs to be reloaded once it has been attached to
323 bool pending_reload_on_attachment_;
325 // Main frame ID of last committed page.
326 int64 main_frame_id_;
328 // Set to |true| if ChromeVox was already injected in main frame.
329 bool chromevox_injected_;
331 // Stores the current zoom factor.
332 double current_zoom_factor_;
334 // Handles find requests and replies for the webview find API.
335 WebviewFindHelper find_helper_;
337 // Handles the JavaScript dialog requests.
338 JavaScriptDialogHelper javascript_dialog_helper_;
340 friend void WebviewFindHelper::DispatchFindUpdateEvent(bool canceled,
343 // Holds the RenderViewContextMenu that has been built but yet to be
344 // shown. This is .Reset() after ShowContextMenu().
345 scoped_ptr<RenderViewContextMenu> pending_menu_;
347 #if defined(OS_CHROMEOS)
348 // Subscription to receive notifications on changes to a11y settings.
349 scoped_ptr<chromeos::AccessibilityStatusSubscription>
350 accessibility_subscription_;
353 std::map<int, int> bridge_id_to_request_id_map_;
355 DISALLOW_COPY_AND_ASSIGN(WebViewGuest);
358 #endif // CHROME_BROWSER_GUEST_VIEW_WEB_VIEW_WEB_VIEW_GUEST_H_