Home | History | Annotate | Download | only in web_view
      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 
    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;
    495     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