1// Copyright 2020 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/webui/interstitials/interstitial_ui.h" 6 7#import <Foundation/Foundation.h> 8#include <memory> 9#include <utility> 10 11#include "base/memory/ref_counted_memory.h" 12#include "base/time/time.h" 13#include "components/grit/dev_ui_components_resources.h" 14#include "ios/chrome/browser/browser_state/chrome_browser_state.h" 15#include "ios/chrome/browser/chrome_url_constants.h" 16#import "ios/chrome/browser/ui/webui/interstitials/interstitial_ui_constants.h" 17#import "ios/chrome/browser/ui/webui/interstitials/interstitial_ui_util.h" 18#import "ios/web/public/security/web_interstitial_delegate.h" 19#import "ios/web/public/web_state.h" 20#include "ios/web/public/webui/url_data_source_ios.h" 21#include "ios/web/public/webui/web_ui_ios.h" 22#include "ios/web/public/webui/web_ui_ios_data_source.h" 23#include "net/base/url_util.h" 24#include "ui/base/resource/resource_bundle.h" 25 26#if !defined(__has_feature) || !__has_feature(objc_arc) 27#error "This file requires ARC support." 28#endif 29 30namespace { 31 32// Implementation of chrome://interstitials demonstration pages. 33class InterstitialHTMLSource : public web::URLDataSourceIOS { 34 public: 35 explicit InterstitialHTMLSource(ChromeBrowserState* browser_state); 36 ~InterstitialHTMLSource() override; 37 InterstitialHTMLSource(InterstitialHTMLSource&& other) = default; 38 InterstitialHTMLSource& operator=(InterstitialHTMLSource&& other) = default; 39 40 private: 41 // web::URLDataSourceIOS: 42 std::string GetSource() const override; 43 void StartDataRequest( 44 const std::string& path, 45 web::URLDataSourceIOS::GotDataCallback callback) override; 46 std::string GetMimeType(const std::string& path) const override; 47 48 // The ChromeBrowserState passed on initialization. Used to construct 49 // WebStates that are passed to WebInterstitialDelegates. 50 ChromeBrowserState* browser_state_ = nullptr; 51}; 52 53} // namespace 54 55#pragma mark - InterstitialHTMLSource 56 57InterstitialHTMLSource::InterstitialHTMLSource( 58 ChromeBrowserState* browser_state) 59 : browser_state_(browser_state) { 60 DCHECK(browser_state_); 61} 62 63InterstitialHTMLSource::~InterstitialHTMLSource() = default; 64 65std::string InterstitialHTMLSource::GetMimeType( 66 const std::string& mime_type) const { 67 return "text/html"; 68} 69 70std::string InterstitialHTMLSource::GetSource() const { 71 return kChromeUIIntersitialsHost; 72} 73 74void InterstitialHTMLSource::StartDataRequest( 75 const std::string& path, 76 web::URLDataSourceIOS::GotDataCallback callback) { 77 std::unique_ptr<web::WebState> web_state = 78 web::WebState::Create(web::WebState::CreateParams(browser_state_)); 79 std::unique_ptr<web::WebInterstitialDelegate> interstitial_delegate; 80 std::string html; 81 // Using this form of the path so we can do exact matching, while ignoring the 82 // query (everything after the ? character). 83 GURL url = GURL(kChromeUIIntersitialsURL).GetWithEmptyPath().Resolve(path); 84 std::string path_without_query = url.path(); 85 if (path_without_query == kChromeInterstitialSslPath) { 86 interstitial_delegate = CreateSslBlockingPageDelegate(web_state.get(), url); 87 } else if (path_without_query == kChromeInterstitialCaptivePortalPath) { 88 interstitial_delegate = 89 CreateCaptivePortalBlockingPageDelegate(web_state.get()); 90 } else if (path_without_query == kChromeInterstitialSafeBrowsingPath) { 91 interstitial_delegate = 92 CreateSafeBrowsingBlockingPageDelegate(web_state.get(), url); 93 } 94 // TODO(crbug.com/1064805): Update the page HTML when a link for an 95 // unsupported interstitial type is tapped. 96 97 // Use the HTML generated from the interstitial delegate if created 98 // successfully. Otherwise, return the default chrome://interstitials HTML. 99 if (interstitial_delegate) { 100 html = interstitial_delegate->GetHtmlContents(); 101 } else { 102 html = ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( 103 IDR_SECURITY_INTERSTITIAL_UI_HTML); 104 } 105 106 std::move(callback).Run(base::RefCountedString::TakeString(&html)); 107} 108 109#pragma mark - InterstitialUI 110 111InterstitialUI::InterstitialUI(web::WebUIIOS* web_ui, const std::string& host) 112 : WebUIIOSController(web_ui, host) { 113 ChromeBrowserState* browser_state = ChromeBrowserState::FromWebUIIOS(web_ui); 114 web::URLDataSourceIOS::Add(browser_state, 115 new InterstitialHTMLSource(browser_state)); 116} 117 118InterstitialUI::~InterstitialUI() = default; 119