1// Copyright 2017 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#import "ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.h" 6 7#include "base/check_op.h" 8#include "base/ios/ios_util.h" 9#import "ios/chrome/browser/ui/fullscreen/fullscreen_content_adjustment_util.h" 10#import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h" 11#import "ios/chrome/browser/ui/fullscreen/fullscreen_mediator.h" 12#import "ios/chrome/browser/ui/fullscreen/fullscreen_model.h" 13#import "ios/chrome/browser/ui/fullscreen/fullscreen_web_view_proxy_observer.h" 14#import "ios/chrome/browser/ui/fullscreen/scoped_fullscreen_disabler.h" 15#include "ios/chrome/browser/ui/util/ui_util.h" 16#include "ios/public/provider/chrome/browser/chrome_browser_provider.h" 17#import "ios/public/provider/chrome/browser/ui/fullscreen_provider.h" 18#include "ios/web/common/url_util.h" 19#import "ios/web/public/navigation/navigation_context.h" 20#import "ios/web/public/navigation/navigation_item.h" 21#import "ios/web/public/navigation/navigation_manager.h" 22#include "ios/web/public/security/ssl_status.h" 23#import "ios/web/public/ui/crw_web_view_proxy.h" 24#import "ios/web/public/ui/page_display_state.h" 25#import "ios/web/public/web_state.h" 26 27#if !defined(__has_feature) || !__has_feature(objc_arc) 28#error "This file requires ARC support." 29#endif 30 31FullscreenWebStateObserver::FullscreenWebStateObserver( 32 FullscreenController* controller, 33 FullscreenModel* model, 34 FullscreenMediator* mediator) 35 : controller_(controller), 36 model_(model), 37 mediator_(mediator), 38 web_view_proxy_observer_([[FullscreenWebViewProxyObserver alloc] 39 initWithModel:model_ 40 mediator:mediator]) { 41 DCHECK(controller_); 42 DCHECK(model_); 43} 44 45FullscreenWebStateObserver::~FullscreenWebStateObserver() = default; 46 47void FullscreenWebStateObserver::SetWebState(web::WebState* web_state) { 48 if (web_state_ == web_state) 49 return; 50 if (web_state_) 51 web_state_->RemoveObserver(this); 52 web_state_ = web_state; 53 if (web_state_) { 54 web_state_->AddObserver(this); 55 // The toolbar should be visible whenever the current tab changes. 56 model_->ResetForNavigation(); 57 } 58 mediator_->SetWebState(web_state); 59 // Update the scroll view replacement handler's proxy. 60 web_view_proxy_observer_.proxy = 61 web_state_ ? web_state_->GetWebViewProxy() : nil; 62} 63 64void FullscreenWebStateObserver::WasShown(web::WebState* web_state) { 65 // Show the toolbars when a WebState is shown. 66 model_->ResetForNavigation(); 67} 68 69void FullscreenWebStateObserver::DidFinishNavigation( 70 web::WebState* web_state, 71 web::NavigationContext* navigation_context) { 72 const GURL& navigation_url = navigation_context->GetUrl(); 73 bool url_changed = web::GURLByRemovingRefFromGURL(navigation_url) != 74 web::GURLByRemovingRefFromGURL(last_navigation_url_); 75 last_navigation_url_ = navigation_url; 76 77 // Due to limitations in WKWebView's rendering, different MIME types must be 78 // inset using different techniques: 79 // - PDFs need to be inset using the scroll view's |contentInset| property or 80 // the floating page indicator is laid out incorrectly. 81 // - For normal pages, using |contentInset| breaks the layout of fixed- 82 // position DOM elements, so top padding must be accomplished by updating 83 // the WKWebView's frame. 84 bool is_pdf = web_state->GetContentsMimeType() == "application/pdf"; 85 id<CRWWebViewProxy> web_view_proxy = web_state->GetWebViewProxy(); 86 web_view_proxy.shouldUseViewContentInset = is_pdf; 87 88 model_->SetResizesScrollView(!is_pdf && !ios::GetChromeBrowserProvider() 89 ->GetFullscreenProvider() 90 ->IsInitialized()); 91 92 // Only reset the model for document-changing navigations or same-document 93 // navigations that update the visible URL. 94 if (!navigation_context->IsSameDocument() || url_changed) 95 model_->ResetForNavigation(); 96} 97 98void FullscreenWebStateObserver::DidStartLoading(web::WebState* web_state) { 99 // This is done to show the toolbar when navigating to a page that is 100 // considered as being in the SameDocument by the NavigationContext, so the 101 // toolbar isn't shown in the DidFinishNavigation. For example this is 102 // needed to load AMP pages from Google Search Result Page. 103 controller_->ExitFullscreen(); 104} 105 106void FullscreenWebStateObserver::WebStateDestroyed(web::WebState* web_state) { 107 DCHECK_EQ(web_state, web_state_); 108 SetWebState(nullptr); 109} 110