1 // Copyright 2019 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 WEBLAYER_BROWSER_TAB_IMPL_H_ 6 #define WEBLAYER_BROWSER_TAB_IMPL_H_ 7 8 #include <memory> 9 #include <set> 10 11 #include "base/callback_forward.h" 12 #include "base/macros.h" 13 #include "base/memory/weak_ptr.h" 14 #include "base/observer_list.h" 15 #include "base/strings/string16.h" 16 #include "build/build_config.h" 17 #include "components/find_in_page/find_result_observer.h" 18 #include "content/public/browser/web_contents_delegate.h" 19 #include "content/public/browser/web_contents_observer.h" 20 #include "content/public/common/browser_controls_state.h" 21 #include "weblayer/browser/i18n_util.h" 22 #include "weblayer/public/tab.h" 23 24 #if defined(OS_ANDROID) 25 #include "base/android/scoped_java_ref.h" 26 #include "weblayer/browser/browser_controls_navigation_state_handler_delegate.h" 27 #endif 28 29 namespace js_injection { 30 class JsCommunicationHost; 31 } 32 33 namespace autofill { 34 class AutofillProvider; 35 } // namespace autofill 36 37 namespace blink { 38 namespace web_pref { 39 struct WebPreferences; 40 } 41 } // namespace blink 42 43 namespace content { 44 class RenderWidgetHostView; 45 class WebContents; 46 struct ContextMenuParams; 47 } 48 49 namespace gfx { 50 class Rect; 51 class Size; 52 } // namespace gfx 53 54 namespace sessions { 55 class SessionTabHelperDelegate; 56 } 57 58 namespace weblayer { 59 class BrowserControlsNavigationStateHandler; 60 class BrowserImpl; 61 class FullscreenDelegate; 62 class NavigationControllerImpl; 63 class NewTabDelegate; 64 class ProfileImpl; 65 66 #if defined(OS_ANDROID) 67 class BrowserControlsContainerView; 68 enum class ControlsVisibilityReason; 69 class WebMessageHostFactoryProxy; 70 #endif 71 72 class TabImpl : public Tab, 73 public content::WebContentsDelegate, 74 public content::WebContentsObserver, 75 #if defined(OS_ANDROID) 76 public BrowserControlsNavigationStateHandlerDelegate, 77 #endif 78 public find_in_page::FindResultObserver { 79 public: 80 enum class ScreenShotErrors { 81 kNone = 0, 82 kScaleOutOfRange, 83 kTabNotActive, 84 kWebContentsNotVisible, 85 kNoSurface, 86 kNoRenderWidgetHostView, 87 kNoWindowAndroid, 88 kEmptyViewport, 89 kHiddenByControls, 90 kScaledToEmpty, 91 kCaptureFailed, 92 kBitmapAllocationFailed, 93 }; 94 95 class DataObserver { 96 public: 97 // Called when SetData() is called on |tab|. 98 virtual void OnDataChanged( 99 TabImpl* tab, 100 const std::map<std::string, std::string>& data) = 0; 101 }; 102 103 // TODO(sky): investigate a better way to not have so many ifdefs. 104 #if defined(OS_ANDROID) 105 TabImpl(ProfileImpl* profile, 106 const base::android::JavaParamRef<jobject>& java_impl, 107 std::unique_ptr<content::WebContents> web_contents); 108 #endif 109 explicit TabImpl(ProfileImpl* profile, 110 std::unique_ptr<content::WebContents> web_contents, 111 const std::string& guid = std::string()); 112 ~TabImpl() override; 113 114 // Returns the TabImpl from the specified WebContents (which may be null), or 115 // null if |web_contents| was not created by a TabImpl. 116 static TabImpl* FromWebContents(content::WebContents* web_contents); 117 118 static std::set<TabImpl*> GetAllTabImpl(); 119 profile()120 ProfileImpl* profile() { return profile_; } 121 set_browser(BrowserImpl * browser)122 void set_browser(BrowserImpl* browser) { browser_ = browser; } browser()123 BrowserImpl* browser() { return browser_; } 124 web_contents()125 content::WebContents* web_contents() const { return web_contents_.get(); } 126 has_new_tab_delegate()127 bool has_new_tab_delegate() const { return new_tab_delegate_ != nullptr; } new_tab_delegate()128 NewTabDelegate* new_tab_delegate() const { return new_tab_delegate_; } 129 130 // Called from Browser when this Tab is losing active status. 131 void OnLosingActive(); 132 133 bool IsActive(); 134 135 void ShowContextMenu(const content::ContextMenuParams& params); 136 137 #if defined(OS_ANDROID) GetJavaTab()138 base::android::ScopedJavaGlobalRef<jobject> GetJavaTab() { 139 return java_impl_; 140 } 141 desktop_user_agent_enabled()142 bool desktop_user_agent_enabled() { return desktop_user_agent_enabled_; } 143 144 // Call this method to disable integration with the system-level Autofill 145 // infrastructure. Useful in conjunction with InitializeAutofillForTests(). 146 // Should be called early in the lifetime of WebLayer, and in 147 // particular, must be called before the TabImpl is attached to the browser 148 // on the Java side to have the desired effect. 149 static void DisableAutofillSystemIntegrationForTesting(); 150 151 base::android::ScopedJavaLocalRef<jobject> GetWebContents(JNIEnv* env); 152 void SetBrowserControlsContainerViews( 153 JNIEnv* env, 154 jlong native_top_browser_controls_container_view, 155 jlong native_bottom_browser_controls_container_view); 156 void ExecuteScript(JNIEnv* env, 157 const base::android::JavaParamRef<jstring>& script, 158 bool use_separate_isolate, 159 const base::android::JavaParamRef<jobject>& callback); 160 void SetJavaImpl(JNIEnv* env, 161 const base::android::JavaParamRef<jobject>& impl); 162 163 // Invoked every time that the Java-side AutofillProvider instance is 164 // changed (set to null or to a new object). On first invocation with a non- 165 // null object initializes the native Autofill infrastructure. On 166 // subsequent invocations updates the association of that native 167 // infrastructure with its Java counterpart. 168 void OnAutofillProviderChanged( 169 JNIEnv* env, 170 const base::android::JavaParamRef<jobject>& autofill_provider); 171 void UpdateBrowserControlsConstraint(JNIEnv* env, 172 jint constraint, 173 jboolean animate); 174 175 base::android::ScopedJavaLocalRef<jstring> GetGuid(JNIEnv* env); 176 void CaptureScreenShot( 177 JNIEnv* env, 178 jfloat scale, 179 const base::android::JavaParamRef<jobject>& value_callback); 180 181 jboolean SetData(JNIEnv* env, 182 const base::android::JavaParamRef<jobjectArray>& data); 183 base::android::ScopedJavaLocalRef<jobjectArray> GetData(JNIEnv* env); 184 jboolean IsRendererControllingBrowserControlsOffsets(JNIEnv* env); 185 base::android::ScopedJavaLocalRef<jstring> RegisterWebMessageCallback( 186 JNIEnv* env, 187 const base::android::JavaParamRef<jstring>& js_object_name, 188 const base::android::JavaParamRef<jobjectArray>& origins, 189 const base::android::JavaParamRef<jobject>& client); 190 void UnregisterWebMessageCallback( 191 JNIEnv* env, 192 const base::android::JavaParamRef<jstring>& js_object_name); 193 jboolean CanTranslate(JNIEnv* env); 194 void ShowTranslateUi(JNIEnv* env); 195 void RemoveTabFromBrowserBeforeDestroying(JNIEnv* env); 196 void SetTranslateTargetLanguage( 197 JNIEnv* env, 198 const base::android::JavaParamRef<jstring>& translate_target_lang); 199 void SetDesktopUserAgentEnabled(JNIEnv* env, jboolean enable); 200 jboolean IsDesktopUserAgentEnabled(JNIEnv* env); 201 void Download(JNIEnv* env, jlong native_context_menu_params); 202 #endif 203 error_page_delegate()204 ErrorPageDelegate* error_page_delegate() { return error_page_delegate_; } 205 206 void AddDataObserver(DataObserver* observer); 207 void RemoveDataObserver(DataObserver* observer); 208 google_accounts_delegate()209 GoogleAccountsDelegate* google_accounts_delegate() { 210 return google_accounts_delegate_; 211 } 212 213 // Tab: 214 Browser* GetBrowser() override; 215 void SetErrorPageDelegate(ErrorPageDelegate* delegate) override; 216 void SetFullscreenDelegate(FullscreenDelegate* delegate) override; 217 void SetNewTabDelegate(NewTabDelegate* delegate) override; 218 void SetGoogleAccountsDelegate(GoogleAccountsDelegate* delegate) override; 219 void AddObserver(TabObserver* observer) override; 220 void RemoveObserver(TabObserver* observer) override; 221 NavigationController* GetNavigationController() override; 222 void ExecuteScript(const base::string16& script, 223 bool use_separate_isolate, 224 JavaScriptResultCallback callback) override; 225 const std::string& GetGuid() override; 226 void SetData(const std::map<std::string, std::string>& data) override; 227 const std::map<std::string, std::string>& GetData() override; 228 base::string16 AddWebMessageHostFactory( 229 std::unique_ptr<WebMessageHostFactory> factory, 230 const base::string16& js_object_name, 231 const std::vector<std::string>& js_origins) override; 232 void RemoveWebMessageHostFactory( 233 const base::string16& js_object_name) override; 234 std::unique_ptr<FaviconFetcher> CreateFaviconFetcher( 235 FaviconFetcherDelegate* delegate) override; 236 #if !defined(OS_ANDROID) 237 void AttachToView(views::WebView* web_view) override; 238 #endif 239 240 void WebPreferencesChanged(); 241 void SetWebPreferences(blink::web_pref::WebPreferences* prefs); 242 243 // Executes |script| with a user gesture. 244 void ExecuteScriptWithUserGestureForTests(const base::string16& script); 245 246 // Initializes the autofill system with |provider| for tests. 247 void InitializeAutofillForTests( 248 std::unique_ptr<autofill::AutofillProvider> provider); 249 250 private: 251 // content::WebContentsDelegate: 252 content::WebContents* OpenURLFromTab( 253 content::WebContents* source, 254 const content::OpenURLParams& params) override; 255 void ShowRepostFormWarningDialog(content::WebContents* source) override; 256 void NavigationStateChanged(content::WebContents* source, 257 content::InvalidateTypes changed_flags) override; 258 content::JavaScriptDialogManager* GetJavaScriptDialogManager( 259 content::WebContents* web_contents) override; 260 content::ColorChooser* OpenColorChooser( 261 content::WebContents* web_contents, 262 SkColor color, 263 const std::vector<blink::mojom::ColorSuggestionPtr>& suggestions) 264 override; 265 void RunFileChooser(content::RenderFrameHost* render_frame_host, 266 scoped_refptr<content::FileSelectListener> listener, 267 const blink::mojom::FileChooserParams& params) override; 268 void CreateSmsPrompt(content::RenderFrameHost*, 269 const url::Origin&, 270 const std::string& one_time_code, 271 base::OnceClosure on_confirm, 272 base::OnceClosure on_cancel) override; 273 int GetTopControlsHeight() override; 274 int GetTopControlsMinHeight() override; 275 int GetBottomControlsHeight() override; 276 bool DoBrowserControlsShrinkRendererSize( 277 content::WebContents* web_contents) override; 278 bool OnlyExpandTopControlsAtPageTop() override; 279 bool ShouldAnimateBrowserControlsHeightChanges() override; 280 void RequestMediaAccessPermission( 281 content::WebContents* web_contents, 282 const content::MediaStreamRequest& request, 283 content::MediaResponseCallback callback) override; 284 bool CheckMediaAccessPermission(content::RenderFrameHost* render_frame_host, 285 const GURL& security_origin, 286 blink::mojom::MediaStreamType type) override; 287 void EnterFullscreenModeForTab( 288 content::RenderFrameHost* requesting_frame, 289 const blink::mojom::FullscreenOptions& options) override; 290 void ExitFullscreenModeForTab(content::WebContents* web_contents) override; 291 bool IsFullscreenForTabOrPending( 292 const content::WebContents* web_contents) override; 293 blink::mojom::DisplayMode GetDisplayMode( 294 const content::WebContents* web_contents) override; 295 void AddNewContents(content::WebContents* source, 296 std::unique_ptr<content::WebContents> new_contents, 297 const GURL& target_url, 298 WindowOpenDisposition disposition, 299 const gfx::Rect& initial_rect, 300 bool user_gesture, 301 bool* was_blocked) override; 302 void CloseContents(content::WebContents* source) override; 303 void FindReply(content::WebContents* web_contents, 304 int request_id, 305 int number_of_matches, 306 const gfx::Rect& selection_rect, 307 int active_match_ordinal, 308 bool final_update) override; 309 #if defined(OS_ANDROID) 310 void FindMatchRectsReply(content::WebContents* web_contents, 311 int version, 312 const std::vector<gfx::RectF>& rects, 313 const gfx::RectF& active_rect) override; 314 315 // Pointer arguments are outputs. Check the preconditions for capturing a 316 // screenshot and either set all outputs, or return an error code, in which 317 // case the state of output arguments is undefined. 318 ScreenShotErrors PrepareForCaptureScreenShot( 319 float scale, 320 content::RenderWidgetHostView** rwhv, 321 gfx::Rect* src_rect, 322 gfx::Size* output_size); 323 324 void UpdateBrowserControlsState(content::BrowserControlsState new_state, 325 bool animate); 326 #endif 327 328 // content::WebContentsObserver: 329 void RenderProcessGone(base::TerminationStatus status) override; 330 void DidChangeVisibleSecurityState() override; 331 332 // find_in_page::FindResultObserver: 333 void OnFindResultAvailable(content::WebContents* web_contents) override; 334 335 #if defined(OS_ANDROID) 336 // BrowserControlsNavigationStateHandlerDelegate: 337 void OnBrowserControlsStateStateChanged( 338 ControlsVisibilityReason reason, 339 content::BrowserControlsState state) override; 340 void OnUpdateBrowserControlsStateBecauseOfProcessSwitch( 341 bool did_commit) override; 342 #endif 343 344 // Called from closure supplied to delegate to exit fullscreen. 345 void OnExitFullscreen(); 346 347 void UpdateRendererPrefs(bool should_sync_prefs); 348 349 void InitializeAutofill(); 350 351 // Returns the FindTabHelper for the page, or null if none exists. 352 find_in_page::FindTabHelper* GetFindTabHelper(); 353 354 static sessions::SessionTabHelperDelegate* GetSessionServiceTabHelperDelegate( 355 content::WebContents* web_contents); 356 357 #if defined(OS_ANDROID) 358 void SetBrowserControlsConstraint(ControlsVisibilityReason reason, 359 content::BrowserControlsState constraint); 360 #endif 361 362 void UpdateBrowserVisibleSecurityStateIfNecessary(); 363 364 bool SetDataInternal(const std::map<std::string, std::string>& data); 365 366 BrowserImpl* browser_ = nullptr; 367 ErrorPageDelegate* error_page_delegate_ = nullptr; 368 FullscreenDelegate* fullscreen_delegate_ = nullptr; 369 NewTabDelegate* new_tab_delegate_ = nullptr; 370 GoogleAccountsDelegate* google_accounts_delegate_ = nullptr; 371 ProfileImpl* profile_; 372 std::unique_ptr<content::WebContents> web_contents_; 373 std::unique_ptr<NavigationControllerImpl> navigation_controller_; 374 base::ObserverList<TabObserver>::Unchecked observers_; 375 std::unique_ptr<i18n::LocaleChangeSubscription> locale_change_subscription_; 376 377 #if defined(OS_ANDROID) 378 BrowserControlsContainerView* top_controls_container_view_ = nullptr; 379 BrowserControlsContainerView* bottom_controls_container_view_ = nullptr; 380 base::android::ScopedJavaGlobalRef<jobject> java_impl_; 381 std::unique_ptr<BrowserControlsNavigationStateHandler> 382 browser_controls_navigation_state_handler_; 383 384 // Last value supplied to UpdateBrowserControlsConstraint(). This *constraint* 385 // can be SHOWN, if for example a modal dialog is forcing the controls to be 386 // visible, HIDDEN, if for example fullscreen is forcing the controls to be 387 // hidden, or BOTH, if either state is viable (e.g. during normal browsing). 388 // When BOTH, the actual current state could be showing or hidden. 389 content::BrowserControlsState 390 current_browser_controls_visibility_constraint_ = 391 content::BROWSER_CONTROLS_STATE_SHOWN; 392 393 std::map<std::string, std::unique_ptr<WebMessageHostFactoryProxy>> 394 js_name_to_proxy_; 395 396 bool desktop_user_agent_enabled_ = false; 397 #endif 398 399 bool is_fullscreen_ = false; 400 // Set to true doing EnterFullscreenModeForTab(). 401 bool processing_enter_fullscreen_ = false; 402 403 std::unique_ptr<autofill::AutofillProvider> autofill_provider_; 404 405 const std::string guid_; 406 407 std::map<std::string, std::string> data_; 408 base::ObserverList<DataObserver>::Unchecked data_observers_; 409 410 base::string16 title_; 411 412 std::unique_ptr<js_injection::JsCommunicationHost> js_communication_host_; 413 414 base::WeakPtrFactory<TabImpl> weak_ptr_factory_{this}; 415 416 DISALLOW_COPY_AND_ASSIGN(TabImpl); 417 }; 418 419 } // namespace weblayer 420 421 #endif // WEBLAYER_BROWSER_TAB_IMPL_H_ 422