// Copyright 2013 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/chrome/browser/shared/model/url/url_util.h"

#import <array>
#import <string_view>

#import "base/strings/sys_string_conversions.h"
#import "ios/chrome/browser/shared/model/url/chrome_url_constants.h"
#import "ios/components/webui/web_ui_url_constants.h"
#import "net/base/apple/url_conversions.h"
#import "testing/gtest_mac.h"
#import "testing/platform_test.h"
#import "url/gurl.h"

namespace {

using ChromeURLUtilTest = PlatformTest;

TEST_F(ChromeURLUtilTest, TestIsExternalFileReference) {
  GURL external_url("chrome://external-file/foo/bar");
  GURL not_external_url("chrome://foo/bar");
  GURL still_not_external_url("http://external-file/foo/bar");
  EXPECT_TRUE(UrlIsExternalFileReference(external_url));
  EXPECT_FALSE(UrlIsExternalFileReference(not_external_url));
  EXPECT_FALSE(UrlIsExternalFileReference(still_not_external_url));
}

TEST_F(ChromeURLUtilTest, TestUrlIsDownloadedFile) {
  GURL downloaded_file_url("chrome://downloads/fileName");
  GURL external_file_url("chrome://external-file/fileName");
  GURL not_downloaded_file_url("http://downloads/fileName");
  EXPECT_TRUE(UrlIsDownloadedFile(downloaded_file_url));
  EXPECT_FALSE(UrlIsDownloadedFile(external_file_url));
  EXPECT_FALSE(UrlIsDownloadedFile(not_downloaded_file_url));
}

constexpr auto kSchemeTestData = std::to_array<std::string_view>({
    "http://foo.com",
    "https://foo.com",
    "data:text/html;charset=utf-8,Hello",
    "about:blank",
    "chrome://settings",
});

// Tests UrlHasChromeScheme with NSURL* parameter.
TEST_F(ChromeURLUtilTest, NSURLHasChromeScheme) {
  for (const std::string_view url : kSchemeTestData) {
    NSURL* nsurl = [NSURL URLWithString:base::SysUTF8ToNSString(url)];
    bool nsurl_result = UrlHasChromeScheme(nsurl);
    EXPECT_EQ(GURL(url).SchemeIs(kChromeUIScheme), nsurl_result)
        << "Scheme check failed for " << url;
  }
}

// Tests UrlHasChromeScheme with const GURL& paramter.
TEST_F(ChromeURLUtilTest, GURLHasChromeScheme) {
  for (const std::string_view url : kSchemeTestData) {
    bool result = UrlHasChromeScheme(GURL(url));
    EXPECT_EQ(GURL(url).SchemeIs(kChromeUIScheme), result)
        << "Scheme check failed for " << url;
  }
}

TEST_F(ChromeURLUtilTest, GetBundleURLScheme) {
  // Verifies that there is some default values.
  ChromeAppConstants* constants = [ChromeAppConstants sharedInstance];
  NSString* originalScheme = [constants bundleURLScheme];
  EXPECT_GT([originalScheme length], 0U);

  // Verifies that Chrome scheme can be reset for testing.
  [constants setCallbackSchemeForTesting:@"blah"];
  EXPECT_NSEQ(@"blah", [constants bundleURLScheme]);

  // Resets state in case of further tests.
  [constants setCallbackSchemeForTesting:originalScheme];
}

TEST_F(ChromeURLUtilTest, GetAllBundleURLSchemes) {
  // Verifies that there is at least 3 scheme (regular, secure and callback).
  ChromeAppConstants* constants = [ChromeAppConstants sharedInstance];
  NSArray* schemes = [constants allBundleURLSchemes];
  EXPECT_GT([schemes count], 2U);

  // Verifies that at least the main unit test scheme is in returned schemes.
  NSString* unittestScheme = @"ios-chrome-unittests.http";
  EXPECT_TRUE([schemes containsObject:unittestScheme]);
}

TEST_F(ChromeURLUtilTest, UrlHasAppStoreScheme) {
  EXPECT_TRUE(UrlHasAppStoreScheme(
      GURL("itms://itunes.apple.com/us/app/appname/id123")));
  EXPECT_TRUE(UrlHasAppStoreScheme(
      GURL("itmss://itunes.apple.com/us/app/appname/id123")));
  EXPECT_TRUE(UrlHasAppStoreScheme(
      GURL("itms-apps://itunes.apple.com/us/app/appname/id123")));
  EXPECT_TRUE(UrlHasAppStoreScheme(
      GURL("itms-appss://itunes.apple.com/us/app/appname/id123")));
  EXPECT_TRUE(UrlHasAppStoreScheme(
      GURL("itms-books://itunes.apple.com/us/app/appname/id123")));
  EXPECT_TRUE(UrlHasAppStoreScheme(
      GURL("itms-bookss://itunes.apple.com/us/app/appname/id123")));
  EXPECT_TRUE(UrlHasAppStoreScheme(
      GURL("itms-services://?action=download-manifest&url=https://example.com/"
           "app.plist")));
  EXPECT_TRUE(
      UrlHasAppStoreScheme(GURL("itms-beta://testflight.apple.com/join/123")));
  EXPECT_TRUE(
      UrlHasAppStoreScheme(GURL("itms-betas://testflight.apple.com/join/123")));
  EXPECT_TRUE(
      UrlHasAppStoreScheme(GURL("itms-watch://testflight.apple.com/join/123")));
  EXPECT_TRUE(UrlHasAppStoreScheme(
      GURL("itms-watchs://testflight.apple.com/join/123")));
  EXPECT_TRUE(UrlHasAppStoreScheme(
      GURL("itms-podcasts://testflight.apple.com/join/123")));
  EXPECT_TRUE(UrlHasAppStoreScheme(
      GURL("itms-podcastss://testflight.apple.com/join/123")));

  EXPECT_FALSE(UrlHasAppStoreScheme(
      GURL("https://itunes.apple.com/us/app/appname/id123")));
  EXPECT_FALSE(UrlHasAppStoreScheme(
      GURL("http://itunes.apple.com/us/app/appname/id123")));
  EXPECT_FALSE(UrlHasAppStoreScheme(GURL("not-itms://foo")));
}

}  // namespace
