• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #ifndef CHROME_BROWSER_GUEST_VIEW_WEB_VIEW_WEB_VIEW_GUEST_H_
6 #define CHROME_BROWSER_GUEST_VIEW_WEB_VIEW_WEB_VIEW_GUEST_H_
7 
8 #include <vector>
9 
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/browser/guest_view/web_view/web_view_permission_types.h"
16 #include "chrome/common/extensions/api/webview.h"
17 #include "content/public/browser/javascript_dialog_manager.h"
18 #include "content/public/browser/notification_registrar.h"
19 #include "third_party/WebKit/public/web/WebFindOptions.h"
20 
21 #if defined(OS_CHROMEOS)
22 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
23 #endif
24 
25 namespace webview_api = extensions::api::webview;
26 
27 class RenderViewContextMenu;
28 
29 namespace extensions {
30 class ScriptExecutor;
31 class WebviewFindFunction;
32 }  // namespace extensions
33 
34 namespace ui {
35 class SimpleMenuModel;
36 }  // namespace ui
37 
38 // A WebViewGuest provides the browser-side implementation of the <webview> API
39 // and manages the dispatch of <webview> extension events. WebViewGuest is
40 // created on attachment. That is, when a guest WebContents is associated with
41 // a particular embedder WebContents. This happens on either initial navigation
42 // or through the use of the New Window API, when a new window is attached to
43 // a particular <webview>.
44 class WebViewGuest : public GuestView<WebViewGuest>,
45                      public content::NotificationObserver {
46  public:
47   WebViewGuest(int guest_instance_id,
48                content::WebContents* guest_web_contents,
49                const std::string& embedder_extension_id);
50 
51   // For WebViewGuest, we create special guest processes, which host the
52   // tag content separately from the main application that embeds the tag.
53   // A <webview> can specify both the partition name and whether the storage
54   // for that partition should be persisted. Each tag gets a SiteInstance with
55   // a specially formatted URL, based on the application it is hosted by and
56   // the partition requested by it. The format for that URL is:
57   // chrome-guest://partition_domain/persist?partition_name
58   static bool GetGuestPartitionConfigForSite(const GURL& site,
59                                              std::string* partition_domain,
60                                              std::string* partition_name,
61                                              bool* in_memory);
62 
63   // Returns guestview::kInstanceIDNone if |contents| does not correspond to a
64   // WebViewGuest.
65   static int GetViewInstanceId(content::WebContents* contents);
66   // Parses partition related parameters from |extra_params|.
67   // |storage_partition_id| is the parsed partition ID and |persist_storage|
68   // specifies whether or not the partition is in memory.
69   static void ParsePartitionParam(const base::DictionaryValue* extra_params,
70                                   std::string* storage_partition_id,
71                                   bool* persist_storage);
72   static const char Type[];
73 
74   // Request navigating the guest to the provided |src| URL.
75   void NavigateGuest(const std::string& src);
76 
77   typedef std::vector<linked_ptr<webview_api::ContextMenuItem> > MenuItemVector;
78   // Shows the context menu for the guest.
79   // |items| acts as a filter. This restricts the current context's default
80   // menu items to contain only the items from |items|.
81   // |items| == NULL means no filtering will be applied.
82   void ShowContextMenu(int request_id, const MenuItemVector* items);
83 
84   // Sets the frame name of the guest.
85   void SetName(const std::string& name);
86 
87   // Set the zoom factor.
88   void SetZoom(double zoom_factor);
89 
90   // GuestViewBase implementation.
91   virtual void DidAttachToEmbedder() OVERRIDE;
92   virtual void DidStopLoading() OVERRIDE;
93   virtual void EmbedderDestroyed() OVERRIDE;
94   virtual void GuestDestroyed() OVERRIDE;
95   virtual bool IsDragAndDropEnabled() const OVERRIDE;
96   virtual void WillAttachToEmbedder() OVERRIDE;
97   virtual void WillDestroy() OVERRIDE;
98 
99   // WebContentsDelegate implementation.
100   virtual bool AddMessageToConsole(content::WebContents* source,
101                                    int32 level,
102                                    const base::string16& message,
103                                    int32 line_no,
104                                    const base::string16& source_id) OVERRIDE;
105   virtual void LoadProgressChanged(content::WebContents* source,
106                                    double progress) OVERRIDE;
107   virtual void CloseContents(content::WebContents* source) OVERRIDE;
108   virtual void FindReply(content::WebContents* source,
109                          int request_id,
110                          int number_of_matches,
111                          const gfx::Rect& selection_rect,
112                          int active_match_ordinal,
113                          bool final_update) OVERRIDE;
114   virtual bool HandleContextMenu(
115       const content::ContextMenuParams& params) OVERRIDE;
116   virtual void HandleKeyboardEvent(
117       content::WebContents* source,
118       const content::NativeWebKeyboardEvent& event) OVERRIDE;
119   virtual void RendererResponsive(content::WebContents* source) OVERRIDE;
120   virtual void RendererUnresponsive(content::WebContents* source) OVERRIDE;
121   virtual void RequestMediaAccessPermission(
122       content::WebContents* source,
123       const content::MediaStreamRequest& request,
124       const content::MediaResponseCallback& callback) OVERRIDE;
125   virtual void CanDownload(content::RenderViewHost* render_view_host,
126                            const GURL& url,
127                            const std::string& request_method,
128                            const base::Callback<void(bool)>& callback) OVERRIDE;
129   virtual content::JavaScriptDialogManager*
130       GetJavaScriptDialogManager() OVERRIDE;
131   virtual content::ColorChooser* OpenColorChooser(
132       content::WebContents* web_contents,
133       SkColor color,
134       const std::vector<content::ColorSuggestion>& suggestions) OVERRIDE;
135   virtual void RunFileChooser(
136       content::WebContents* web_contents,
137       const content::FileChooserParams& params) OVERRIDE;
138   virtual void AddNewContents(content::WebContents* source,
139                               content::WebContents* new_contents,
140                               WindowOpenDisposition disposition,
141                               const gfx::Rect& initial_pos,
142                               bool user_gesture,
143                               bool* was_blocked) OVERRIDE;
144   virtual content::WebContents* OpenURLFromTab(
145       content::WebContents* source,
146       const content::OpenURLParams& params) OVERRIDE;
147   virtual void WebContentsCreated(content::WebContents* source_contents,
148                                   int opener_render_frame_id,
149                                   const base::string16& frame_name,
150                                   const GURL& target_url,
151                                   content::WebContents* new_contents) OVERRIDE;
152 
153   // BrowserPluginGuestDelegate implementation.
154   virtual void SizeChanged(const gfx::Size& old_size, const gfx::Size& new_size)
155       OVERRIDE;
156   virtual void RequestPointerLockPermission(
157       bool user_gesture,
158       bool last_unlocked_by_target,
159       const base::Callback<void(bool)>& callback) OVERRIDE;
160   // NotificationObserver implementation.
161   virtual void Observe(int type,
162                        const content::NotificationSource& source,
163                        const content::NotificationDetails& details) OVERRIDE;
164 
165   // Returns the current zoom factor.
166   double GetZoom();
167 
168   // Begin or continue a find request.
169   void Find(const base::string16& search_text,
170             const blink::WebFindOptions& options,
171             scoped_refptr<extensions::WebviewFindFunction> find_function);
172 
173   // Conclude a find request to clear highlighting.
174   void StopFinding(content::StopFindAction);
175 
176   // If possible, navigate the guest to |relative_index| entries away from the
177   // current navigation entry.
178   void Go(int relative_index);
179 
180   // Reload the guest.
181   void Reload();
182 
183   typedef base::Callback<void(bool /* allow */,
184                               const std::string& /* user_input */)>
185       PermissionResponseCallback;
186   int RequestPermission(
187       WebViewPermissionType permission_type,
188       const base::DictionaryValue& request_info,
189       const PermissionResponseCallback& callback,
190       bool allowed_by_default);
191 
192   // Requests Geolocation Permission from the embedder.
193   void RequestGeolocationPermission(int bridge_id,
194                                     const GURL& requesting_frame,
195                                     bool user_gesture,
196                                     const base::Callback<void(bool)>& callback);
197   void CancelGeolocationPermissionRequest(int bridge_id);
198 
199   void RequestFileSystemPermission(const GURL& url,
200                                    bool allowed_by_default,
201                                    const base::Callback<void(bool)>& callback);
202 
203   enum PermissionResponseAction {
204     DENY,
205     ALLOW,
206     DEFAULT
207   };
208 
209   enum SetPermissionResult {
210     SET_PERMISSION_INVALID,
211     SET_PERMISSION_ALLOWED,
212     SET_PERMISSION_DENIED
213   };
214 
215   // Responds to the permission request |request_id| with |action| and
216   // |user_input|. Returns whether there was a pending request for the provided
217   // |request_id|.
218   SetPermissionResult SetPermission(int request_id,
219                                     PermissionResponseAction action,
220                                     const std::string& user_input);
221 
222   // Overrides the user agent for this guest.
223   // This affects subsequent guest navigations.
224   void SetUserAgentOverride(const std::string& user_agent_override);
225 
226   // Stop loading the guest.
227   void Stop();
228 
229   // Kill the guest process.
230   void Terminate();
231 
232   // Clears data in the storage partition of this guest.
233   //
234   // Partition data that are newer than |removal_since| will be removed.
235   // |removal_mask| corresponds to bitmask in StoragePartition::RemoveDataMask.
236   bool ClearData(const base::Time remove_since,
237                  uint32 removal_mask,
238                  const base::Closure& callback);
239 
script_executor()240   extensions::ScriptExecutor* script_executor() {
241     return script_executor_.get();
242   }
243 
244   // Called when file system access is requested by the guest content using the
245   // asynchronous HTML5 file system API. The request is plumbed through the
246   // <webview> permission request API. The request will be:
247   // - Allowed if the embedder explicitly allowed it.
248   // - Denied if the embedder explicitly denied.
249   // - Determined by the guest's content settings if the embedder does not
250   // perform an explicit action.
251   // If access was blocked due to the page's content settings,
252   // |blocked_by_policy| should be true, and this function should invoke
253   // OnContentBlocked.
254   static void FileSystemAccessedAsync(int render_process_id,
255                                       int render_frame_id,
256                                       int request_id,
257                                       const GURL& url,
258                                       bool blocked_by_policy);
259 
260   // Called when file system access is requested by the guest content using the
261   // synchronous HTML5 file system API in a worker thread or shared worker. The
262   // request is plumbed through the <webview> permission request API. The
263   // request will be:
264   // - Allowed if the embedder explicitly allowed it.
265   // - Denied if the embedder explicitly denied.
266   // - Determined by the guest's content settings if the embedder does not
267   // perform an explicit action.
268   // If access was blocked due to the page's content settings,
269   // |blocked_by_policy| should be true, and this function should invoke
270   // OnContentBlocked.
271   static void FileSystemAccessedSync(int render_process_id,
272                                      int render_frame_id,
273                                      const GURL& url,
274                                      bool blocked_by_policy,
275                                      IPC::Message* reply_msg);
276 
277  private:
278   virtual ~WebViewGuest();
279 
280   // A map to store the callback for a request keyed by the request's id.
281   struct PermissionResponseInfo {
282     PermissionResponseCallback callback;
283     WebViewPermissionType permission_type;
284     bool allowed_by_default;
285     PermissionResponseInfo();
286     PermissionResponseInfo(const PermissionResponseCallback& callback,
287                            WebViewPermissionType permission_type,
288                            bool allowed_by_default);
289     ~PermissionResponseInfo();
290   };
291 
292   static void RecordUserInitiatedUMA(const PermissionResponseInfo& info,
293                                      bool allow);
294 
295   // Returns the top level items (ignoring submenus) as Value.
296   static scoped_ptr<base::ListValue> MenuModelToValue(
297       const ui::SimpleMenuModel& menu_model);
298 
299   void OnWebViewGeolocationPermissionResponse(
300       int bridge_id,
301       bool user_gesture,
302       const base::Callback<void(bool)>& callback,
303       bool allow,
304       const std::string& user_input);
305 
306   void OnWebViewFileSystemPermissionResponse(
307       const base::Callback<void(bool)>& callback,
308       bool allow,
309       const std::string& user_input);
310 
311   void OnWebViewMediaPermissionResponse(
312       const content::MediaStreamRequest& request,
313       const content::MediaResponseCallback& callback,
314       bool allow,
315       const std::string& user_input);
316 
317   void OnWebViewDownloadPermissionResponse(
318       const base::Callback<void(bool)>& callback,
319       bool allow,
320       const std::string& user_input);
321 
322   void OnWebViewPointerLockPermissionResponse(
323       const base::Callback<void(bool)>& callback,
324       bool allow,
325       const std::string& user_input);
326 
327   void OnWebViewNewWindowResponse(int new_window_instance_id,
328                                   bool allow,
329                                   const std::string& user_input);
330 
331   static void FileSystemAccessedAsyncResponse(int render_process_id,
332                                               int render_frame_id,
333                                               int request_id,
334                                               const GURL& url,
335                                               bool allowed);
336 
337   static void FileSystemAccessedSyncResponse(int render_process_id,
338                                              int render_frame_id,
339                                              const GURL& url,
340                                              IPC::Message* reply_msg,
341                                              bool allowed);
342 
343   // WebContentsObserver implementation.
344   virtual void DidCommitProvisionalLoadForFrame(
345       int64 frame_id,
346       const base::string16& frame_unique_name,
347       bool is_main_frame,
348       const GURL& url,
349       content::PageTransition transition_type,
350       content::RenderViewHost* render_view_host) OVERRIDE;
351   virtual void DidFailProvisionalLoad(
352       int64 frame_id,
353       const base::string16& frame_unique_name,
354       bool is_main_frame,
355       const GURL& validated_url,
356       int error_code,
357       const base::string16& error_description,
358       content::RenderViewHost* render_view_host) OVERRIDE;
359   virtual void DidStartProvisionalLoadForFrame(
360       int64 frame_id,
361       int64 parent_frame_id,
362       bool is_main_frame,
363       const GURL& validated_url,
364       bool is_error_page,
365       bool is_iframe_srcdoc,
366       content::RenderViewHost* render_view_host) OVERRIDE;
367   virtual void DocumentLoadedInFrame(
368       int64 frame_id,
369       content::RenderViewHost* render_view_host) OVERRIDE;
370   virtual bool OnMessageReceived(
371       const IPC::Message& message,
372       content::RenderFrameHost* render_frame_host) OVERRIDE;
373   virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
374   virtual void UserAgentOverrideSet(const std::string& user_agent) OVERRIDE;
375   virtual void RenderViewReady() OVERRIDE;
376 
377   // Informs the embedder of a frame name change.
378   void ReportFrameNameChange(const std::string& name);
379 
380   // Called after the load handler is called in the guest's main frame.
381   void LoadHandlerCalled();
382 
383   // Called when a redirect notification occurs.
384   void LoadRedirect(const GURL& old_url,
385                     const GURL& new_url,
386                     bool is_top_level);
387 
388   void AddWebViewToExtensionRendererState();
389   static void RemoveWebViewFromExtensionRendererState(
390       content::WebContents* web_contents);
391 
392 #if defined(OS_CHROMEOS)
393   // Notification of a change in the state of an accessibility setting.
394   void OnAccessibilityStatusChanged(
395     const chromeos::AccessibilityStatusEventDetails& details);
396 #endif
397 
398   void InjectChromeVoxIfNeeded(content::RenderViewHost* render_view_host);
399 
400   // Bridge IDs correspond to a geolocation request. This method will remove
401   // the bookkeeping for a particular geolocation request associated with the
402   // provided |bridge_id|. It returns the request ID of the geolocation request.
403   int RemoveBridgeID(int bridge_id);
404 
405   void LoadURLWithParams(const GURL& url,
406                          const content::Referrer& referrer,
407                          content::PageTransition transition_type,
408                          content::WebContents* web_contents);
409 
410   void RequestNewWindowPermission(
411       WindowOpenDisposition disposition,
412       const gfx::Rect& initial_bounds,
413       bool user_gesture,
414       content::WebContents* new_contents);
415 
416   // Destroy unattached new windows that have been opened by this
417   // WebViewGuest.
418   void DestroyUnattachedWindows();
419 
420   // Requests resolution of a potentially relative URL.
421   GURL ResolveURL(const std::string& src);
422 
423   // Notification that a load in the guest resulted in abort. Note that |url|
424   // may be invalid.
425   void LoadAbort(bool is_top_level,
426                  const GURL& url,
427                  const std::string& error_type);
428 
429   void OnUpdateFrameName(bool is_top_level, const std::string& name);
430 
431   // Creates a new guest window owned by this WebViewGuest.
432   WebViewGuest* CreateNewGuestWindow(const content::OpenURLParams& params);
433 
434   bool HandleKeyboardShortcuts(const content::NativeWebKeyboardEvent& event);
435 
436   ObserverList<extensions::TabHelper::ScriptExecutionObserver>
437       script_observers_;
438   scoped_ptr<extensions::ScriptExecutor> script_executor_;
439 
440   content::NotificationRegistrar notification_registrar_;
441 
442   // A counter to generate a unique request id for a context menu request.
443   // We only need the ids to be unique for a given WebViewGuest.
444   int pending_context_menu_request_id_;
445 
446   // A counter to generate a unique request id for a permission request.
447   // We only need the ids to be unique for a given WebViewGuest.
448   int next_permission_request_id_;
449 
450   typedef std::map<int, PermissionResponseInfo> RequestMap;
451   RequestMap pending_permission_requests_;
452 
453   // True if the user agent is overridden.
454   bool is_overriding_user_agent_;
455 
456   // Main frame ID of last committed page.
457   int64 main_frame_id_;
458 
459   // Set to |true| if ChromeVox was already injected in main frame.
460   bool chromevox_injected_;
461 
462   // Stores the current zoom factor.
463   double current_zoom_factor_;
464 
465   // Stores the window name of the main frame of the guest.
466   std::string name_;
467 
468   // Handles find requests and replies for the webview find API.
469   WebviewFindHelper find_helper_;
470 
471   // Handles the JavaScript dialog requests.
472   JavaScriptDialogHelper javascript_dialog_helper_;
473 
474   friend void WebviewFindHelper::DispatchFindUpdateEvent(bool canceled,
475                                                          bool final_update);
476 
477   // Holds the RenderViewContextMenu that has been built but yet to be
478   // shown. This is .Reset() after ShowContextMenu().
479   scoped_ptr<RenderViewContextMenu> pending_menu_;
480 
481 #if defined(OS_CHROMEOS)
482   // Subscription to receive notifications on changes to a11y settings.
483   scoped_ptr<chromeos::AccessibilityStatusSubscription>
484       accessibility_subscription_;
485 #endif
486 
487   std::map<int, int> bridge_id_to_request_id_map_;
488 
489   // Tracks the name, and target URL of the new window. Once the first
490   // navigation commits, we no longer track this information.
491   struct NewWindowInfo {
492     GURL url;
493     std::string name;
494     bool changed;
NewWindowInfoNewWindowInfo495     NewWindowInfo(const GURL& url, const std::string& name) :
496         url(url),
497         name(name),
498         changed(false) {}
499   };
500 
501   typedef std::map<WebViewGuest*, NewWindowInfo> PendingWindowMap;
502   PendingWindowMap pending_new_windows_;
503 
504   DISALLOW_COPY_AND_ASSIGN(WebViewGuest);
505 };
506 
507 #endif  // CHROME_BROWSER_GUEST_VIEW_WEB_VIEW_WEB_VIEW_GUEST_H_
508