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