chromium/ios/components/security_interstitials/lookalikes/lookalike_url_blocking_page.mm

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "ios/components/security_interstitials/lookalikes/lookalike_url_blocking_page.h"

#import <utility>

#import "base/strings/string_number_conversions.h"
#import "base/values.h"
#import "components/lookalikes/core/lookalike_url_ui_util.h"
#import "components/lookalikes/core/lookalike_url_util.h"
#import "components/security_interstitials/core/common_string_util.h"
#import "components/security_interstitials/core/metrics_helper.h"
#import "ios/components/security_interstitials/ios_blocking_page_controller_client.h"
#import "ios/components/security_interstitials/ios_blocking_page_metrics_helper.h"

LookalikeUrlBlockingPage::LookalikeUrlBlockingPage(
    web::WebState* web_state,
    const GURL& safe_url,
    const GURL& request_url,
    ukm::SourceId source_id,
    lookalikes::LookalikeUrlMatchType match_type,
    std::unique_ptr<LookalikeUrlControllerClient> client)
    : security_interstitials::IOSSecurityInterstitialPage(web_state,
                                                          request_url,
                                                          client.get()),
      web_state_(web_state),
      controller_(std::move(client)),
      safe_url_(safe_url),
      source_id_(source_id),
      match_type_(match_type) {
  DCHECK(web_state_);
  controller_->metrics_helper()->RecordUserDecision(
      security_interstitials::MetricsHelper::SHOW);
  controller_->metrics_helper()->RecordUserInteraction(
      security_interstitials::MetricsHelper::TOTAL_VISITS);

  // Creating an interstitial without showing it (e.g. from
  // chrome://interstitials) leaks memory, so don't create it here.
}

LookalikeUrlBlockingPage::~LookalikeUrlBlockingPage() {
  // Update metrics when the interstitial is closed or user navigates away.
  ReportUkmForLookalikeUrlBlockingPageIfNeeded(
      source_id_, match_type_,
      lookalikes::LookalikeUrlBlockingPageUserAction::kCloseOrBack,
      /*triggered_by_initial_url=*/false);
}

bool LookalikeUrlBlockingPage::ShouldCreateNewNavigation() const {
  return true;
}

void LookalikeUrlBlockingPage::PopulateInterstitialStrings(
    base::Value::Dict& load_time_data) const {
  // Set a value if backwards navigation is not available, used
  // to change the button text to 'Close page' when there is no
  // suggested URL.
  if (!controller_->CanGoBack()) {
    load_time_data.Set("cant_go_back", true);
  }

  lookalikes::PopulateLookalikeUrlBlockingPageStrings(load_time_data, safe_url_,
                                                      request_url());
}

bool LookalikeUrlBlockingPage::ShouldDisplayURL() const {
  return false;
}

void LookalikeUrlBlockingPage::HandleCommand(
    security_interstitials::SecurityInterstitialCommand command) {
  if (command == security_interstitials::CMD_DONT_PROCEED) {
    controller_->metrics_helper()->RecordUserDecision(
        security_interstitials::MetricsHelper::DONT_PROCEED);
    ReportUkmForLookalikeUrlBlockingPageIfNeeded(
        source_id_, match_type_,
        lookalikes::LookalikeUrlBlockingPageUserAction::kAcceptSuggestion,
        /*triggered_by_initial_url=*/false);
    controller_->GoBack();
  } else if (command == security_interstitials::CMD_PROCEED) {
    controller_->metrics_helper()->RecordUserDecision(
        security_interstitials::MetricsHelper::PROCEED);
    ReportUkmForLookalikeUrlBlockingPageIfNeeded(
        source_id_, match_type_,
        lookalikes::LookalikeUrlBlockingPageUserAction::kClickThrough,
        /*triggered_by_initial_url=*/false);
    controller_->Proceed();
  }
}