[iOS] Disable fullscreen for SadTab.

Additionally, this CL updates CRWGenericContentView's contentSize
adjustment logic to ensure that scrolling doesn't get disabled.

Bug: 807957
Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Change-Id: Idf48f9b79966520f31477b0a58415eb286f037ae
Reviewed-on: https://chromium-review.googlesource.com/917642
Reviewed-by: Eugene But <eugenebut@chromium.org>
Reviewed-by: Kurt Horimoto <kkhorimoto@chromium.org>
Reviewed-by: Justin Cohen <justincohen@chromium.org>
Commit-Queue: Kurt Horimoto <kkhorimoto@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#537450}(cherry picked from commit e8bbb37f4c9a26f147c5623ef88dd7828a53d83b)
Reviewed-on: https://chromium-review.googlesource.com/933304
Cr-Commit-Position: refs/branch-heads/3325@{#563}
Cr-Branched-From: bc084a8b5afa3744a74927344e304c02ae54189f-refs/heads/master@{#530369}
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn
index bc34096..5bec74a 100644
--- a/ios/chrome/browser/web/BUILD.gn
+++ b/ios/chrome/browser/web/BUILD.gn
@@ -38,9 +38,11 @@
     "//components/strings",
     "//ios/chrome/app/strings:ios_strings_grit",
     "//ios/chrome/browser",
+    "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/snapshots",
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui/commands:commands",
+    "//ios/chrome/browser/ui/fullscreen",
     "//ios/chrome/browser/ui/util:util",
     "//ios/web",
     "//ui/base",
diff --git a/ios/chrome/browser/web/sad_tab_tab_helper.h b/ios/chrome/browser/web/sad_tab_tab_helper.h
index 92699c3..71dbd8b 100644
--- a/ios/chrome/browser/web/sad_tab_tab_helper.h
+++ b/ios/chrome/browser/web/sad_tab_tab_helper.h
@@ -10,6 +10,7 @@
 #import "ios/web/public/web_state/web_state_user_data.h"
 
 @protocol SadTabTabHelperDelegate;
+class ScopedFullscreenDisabler;
 
 // SadTabTabHelper listens to RenderProcessGone events and presents a
 // SadTabView view appropriately.
@@ -53,6 +54,10 @@
   // Presents a new SadTabView via the web_state object.
   void PresentSadTab(const GURL& url_causing_failure);
 
+  // Called when the Sad Tab is added or removed from the WebState's content
+  // area.
+  void SetIsShowingSadTab(bool showing_sad_tab);
+
   // Loads the current page after renderer crash while displaying the page
   // placeholder during the load. Reloading the page which was not visible to
   // the user during the crash is a better user experience than presenting
@@ -67,9 +72,16 @@
   // Removes UIApplicationDidBecomeActiveNotification observer.
   void RemoveApplicationDidBecomeActiveObserver();
 
+  // Creates or resets the fullscreen disabler depending on whether the sad tab
+  // is currently visible.
+  void UpdateFullscreenDisabler();
+
   // WebStateObserver:
   void WasShown(web::WebState* web_state) override;
+  void WasHidden(web::WebState* web_state) override;
   void RenderProcessGone(web::WebState* web_state) override;
+  void DidStartNavigation(web::WebState* web_state,
+                          web::NavigationContext* navigation_context) override;
   void DidFinishNavigation(web::WebState* web_state,
                            web::NavigationContext* navigation_context) override;
   void WebStateDestroyed(web::WebState* web_state) override;
@@ -90,6 +102,12 @@
   // used to determine time window for repeated crashes.
   std::unique_ptr<base::ElapsedTimer> last_failed_timer_;
 
+  // Whether a Sad Tab is being shown over |web_state_|'s content area.
+  bool showing_sad_tab_ = false;
+
+  // The fullscreen disabler for when the sad tab is visible.
+  std::unique_ptr<ScopedFullscreenDisabler> fullscreen_disabler_;
+
   // Stores the interval window in seconds during which a second
   // RenderProcessGone failure will be considered a repeat failure.
   double repeat_failure_interval_ = kDefaultRepeatFailureInterval;
diff --git a/ios/chrome/browser/web/sad_tab_tab_helper.mm b/ios/chrome/browser/web/sad_tab_tab_helper.mm
index 03ae967..ec93ada 100644
--- a/ios/chrome/browser/web/sad_tab_tab_helper.mm
+++ b/ios/chrome/browser/web/sad_tab_tab_helper.mm
@@ -12,11 +12,15 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/sys_string_conversions.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
+#include "ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.h"
+#include "ios/chrome/browser/ui/fullscreen/scoped_fullscreen_disabler.h"
 #import "ios/chrome/browser/web/page_placeholder_tab_helper.h"
 #import "ios/chrome/browser/web/sad_tab_tab_helper_delegate.h"
 #import "ios/web/public/navigation_manager.h"
 #include "ios/web/public/web_state/navigation_context.h"
+#include "ios/web/public/web_state/web_state.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -83,6 +87,11 @@
     ReloadTab();
     requires_reload_on_becoming_visible_ = false;
   }
+  UpdateFullscreenDisabler();
+}
+
+void SadTabTabHelper::WasHidden(web::WebState* web_state) {
+  UpdateFullscreenDisabler();
 }
 
 void SadTabTabHelper::RenderProcessGone(web::WebState* web_state) {
@@ -103,6 +112,13 @@
   PresentSadTab(web_state->GetLastCommittedURL());
 }
 
+void SadTabTabHelper::DidStartNavigation(
+    web::WebState* web_state,
+    web::NavigationContext* navigation_context) {
+  // The sad tab is removed when a new navigation begins.
+  SetIsShowingSadTab(false);
+}
+
 void SadTabTabHelper::DidFinishNavigation(
     web::WebState* web_state,
     web::NavigationContext* navigation_context) {
@@ -136,6 +152,15 @@
 
   last_failed_url_ = url_causing_failure;
   last_failed_timer_ = std::make_unique<base::ElapsedTimer>();
+
+  SetIsShowingSadTab(true);
+}
+
+void SadTabTabHelper::SetIsShowingSadTab(bool showing_sad_tab) {
+  if (showing_sad_tab_ != showing_sad_tab) {
+    showing_sad_tab_ = showing_sad_tab;
+    UpdateFullscreenDisabler();
+  }
 }
 
 void SadTabTabHelper::ReloadTab() {
@@ -173,3 +198,20 @@
     application_did_become_active_observer_ = nil;
   }
 }
+
+void SadTabTabHelper::UpdateFullscreenDisabler() {
+  if (showing_sad_tab_ && web_state_->IsVisible()) {
+    ios::ChromeBrowserState* browser_state =
+        ios::ChromeBrowserState::FromBrowserState(
+            web_state_->GetBrowserState());
+    FullscreenController* fullscreen_controller =
+        FullscreenControllerFactory::GetInstance()->GetForBrowserState(
+            browser_state);
+    if (fullscreen_controller) {
+      fullscreen_disabler_ =
+          std::make_unique<ScopedFullscreenDisabler>(fullscreen_controller);
+    }
+  } else {
+    fullscreen_disabler_ = nullptr;
+  }
+}
diff --git a/ios/web/web_state/ui/crw_generic_content_view.mm b/ios/web/web_state/ui/crw_generic_content_view.mm
index 315fe6a..91a5eba 100644
--- a/ios/web/web_state/ui/crw_generic_content_view.mm
+++ b/ios/web/web_state/ui/crw_generic_content_view.mm
@@ -90,10 +90,10 @@
   self.view.frame = CGRectMake(0.0, 0.0, viewSize.width, viewSize.height);
 
   // UIScrollViews only scroll vertically if the content size's height is
-  // greater than that of its content rect.
-  if (viewSize.height <= CGRectGetHeight(contentRect)) {
+  // greater than that of its bounds.
+  if (viewSize.height <= _lastLayoutSize.height) {
     CGFloat singlePixel = 1.0f / [[UIScreen mainScreen] scale];
-    viewSize.height = CGRectGetHeight(contentRect) + singlePixel;
+    viewSize.height = _lastLayoutSize.height + singlePixel;
   }
   self.scrollView.contentSize = viewSize;
 }