1// Copyright 2015 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#include "ios/components/security_interstitials/ios_blocking_page_controller_client.h"
6
7#include "base/bind.h"
8#include "base/check_op.h"
9#include "base/notreached.h"
10#include "base/task/post_task.h"
11#include "components/security_interstitials/core/metrics_helper.h"
12#import "ios/web/public/navigation/navigation_manager.h"
13#include "ios/web/public/navigation/reload_type.h"
14#include "ios/web/public/security/web_interstitial.h"
15#include "ios/web/public/thread/web_task_traits.h"
16#include "ios/web/public/thread/web_thread.h"
17#import "ios/web/public/web_state.h"
18
19#if !defined(__has_feature) || !__has_feature(objc_arc)
20#error "This file requires ARC support."
21#endif
22
23namespace security_interstitials {
24
25IOSBlockingPageControllerClient::IOSBlockingPageControllerClient(
26    web::WebState* web_state,
27    std::unique_ptr<security_interstitials::MetricsHelper> metrics_helper,
28    const std::string& app_locale)
29    : security_interstitials::ControllerClient(std::move(metrics_helper)),
30      web_state_(web_state),
31      web_interstitial_(nullptr),
32      app_locale_(app_locale),
33      weak_factory_(this) {
34  web_state_->AddObserver(this);
35}
36
37IOSBlockingPageControllerClient::~IOSBlockingPageControllerClient() {
38  if (web_state_) {
39    web_state_->RemoveObserver(this);
40  }
41}
42
43void IOSBlockingPageControllerClient::SetWebInterstitial(
44    web::WebInterstitial* web_interstitial) {
45  web_interstitial_ = web_interstitial;
46}
47
48void IOSBlockingPageControllerClient::WebStateDestroyed(
49    web::WebState* web_state) {
50  DCHECK_EQ(web_state_, web_state);
51  web_state_->RemoveObserver(this);
52  web_state_ = nullptr;
53}
54
55bool IOSBlockingPageControllerClient::CanLaunchDateAndTimeSettings() {
56  return false;
57}
58
59void IOSBlockingPageControllerClient::LaunchDateAndTimeSettings() {
60  NOTREACHED();
61}
62
63void IOSBlockingPageControllerClient::GoBack() {
64  if (CanGoBack()) {
65    web_state_->GetNavigationManager()->GoBack();
66  } else {
67    // Closing the tab synchronously is problematic since web state is heavily
68    // involved in the operation and CloseWebState interrupts it, so call
69    // CloseWebState asynchronously.
70    base::PostTask(FROM_HERE, {web::WebThread::UI},
71                   base::BindOnce(&IOSBlockingPageControllerClient::Close,
72                                  weak_factory_.GetWeakPtr()));
73  }
74}
75
76bool IOSBlockingPageControllerClient::CanGoBack() {
77  return web_state_->GetNavigationManager()->CanGoBack();
78}
79
80bool IOSBlockingPageControllerClient::CanGoBackBeforeNavigation() {
81  NOTREACHED();
82  return false;
83}
84
85void IOSBlockingPageControllerClient::GoBackAfterNavigationCommitted() {
86  NOTREACHED();
87}
88
89void IOSBlockingPageControllerClient::Proceed() {
90  DCHECK(web_interstitial_);
91  web_interstitial_->Proceed();
92}
93
94void IOSBlockingPageControllerClient::Reload() {
95  web_state_->GetNavigationManager()->Reload(web::ReloadType::NORMAL,
96                                             true /*check_for_repost*/);
97}
98
99void IOSBlockingPageControllerClient::OpenUrlInCurrentTab(const GURL& url) {
100  web_state_->OpenURL(web::WebState::OpenURLParams(
101      url, web::Referrer(), WindowOpenDisposition::CURRENT_TAB,
102      ui::PAGE_TRANSITION_LINK, false));
103}
104
105void IOSBlockingPageControllerClient::OpenUrlInNewForegroundTab(
106    const GURL& url) {
107  web_state_->OpenURL(web::WebState::OpenURLParams(
108      url, web::Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB,
109      ui::PAGE_TRANSITION_LINK, false));
110}
111
112void IOSBlockingPageControllerClient::OpenEnhancedProtectionSettings() {
113  NOTREACHED() << "Enhanced protection is not supported on iOS.";
114}
115
116const std::string& IOSBlockingPageControllerClient::GetApplicationLocale()
117    const {
118  return app_locale_;
119}
120
121PrefService* IOSBlockingPageControllerClient::GetPrefService() {
122  return nullptr;
123}
124
125const std::string
126IOSBlockingPageControllerClient::GetExtendedReportingPrefName() const {
127  return std::string();
128}
129
130void IOSBlockingPageControllerClient::Close() {
131  if (web_state_) {
132    web_state_->CloseWebState();
133  }
134}
135
136}  // namespace security_interstitials
137