chromium/chromeos/crosapi/cpp/gurl_os_handler_utils.cc

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

#include "chromeos/crosapi/cpp/gurl_os_handler_utils.h"

#include <stddef.h>

#include <string_view>

#include "base/logging.h"
#include "base/strings/string_util.h"
#include "url/url_util.h"

namespace {

// Note that GURL can't operate on the "os://" scheme as it is intentionally
// not a registered scheme.
const char kOsScheme[] = "os";
const char kOsUrlPrefix[] = "os://";
const char kChromeUrlPrefix[] = "chrome://";
const char kChromeUIOSSettingsHost[] = "os-settings";

// The start of the host portion of a GURL which starts with the os scheme.
const size_t kHostStart = sizeof(kOsUrlPrefix) - 1;

GURL NormalizeAshUrl(GURL url,
                     bool keep_path = false,
                     bool keep_query = false) {
  if (!url.is_valid() || !url.has_host()) {
    return GURL();
  }

  // Shortcut.
  if (!url.has_ref() && !url.has_username() && !url.has_password() &&
      (keep_query || !url.has_query()) && !url.has_port() &&
      (keep_path || !url.has_path())) {
    return url;
  }

  GURL::Replacements replacements;
  replacements.ClearPassword();
  if (!keep_path) {
    replacements.ClearPath();
  }
  replacements.ClearPort();
  if (!keep_query) {
    replacements.ClearQuery();
  }
  replacements.ClearRef();
  replacements.ClearUsername();
  return url.ReplaceComponents(replacements);
}

}  // namespace

namespace crosapi {

namespace gurl_os_handler_utils {

GURL SanitizeAshUrl(const GURL& url) {
  return NormalizeAshUrl(url, /*keep_path*/ true, /*keep_query*/ true);
}

GURL GetAshUrlFromLacrosUrl(GURL url) {
  const bool has_os_scheme = HasOsScheme(url);
  if (has_os_scheme) {
    url = GURL(kChromeUrlPrefix + url.spec().substr(kHostStart));
  }

  if (has_os_scheme && url.host() == "settings") {
    // Change os://settings/* into chrome://os-settings/* which will be the long
    // term home for our OS-settings.
    GURL::Replacements replacements;
    replacements.SetHostStr(kChromeUIOSSettingsHost);
    url = url.ReplaceComponents(replacements);
  }

  return url;
}

bool IsAshUrlInList(const GURL& url, const std::vector<GURL>& list) {
  return std::any_of(list.begin(), list.end(), [&](const GURL& elem) {
    DCHECK(elem.is_valid());
    DCHECK_EQ(elem, NormalizeAshUrl(elem));
    return elem == NormalizeAshUrl(url);
  });
}

bool HasOsScheme(const GURL& url) {
  if (!url.is_valid() || url.spec().length() <= strlen(kOsUrlPrefix))
    return false;

  // Do not use "url.SchemeIs(kOsScheme)" here as it would require further
  // parsing of the "://" portion to see if the Url is also valid.
  return base::StartsWith(url.spec(), kOsUrlPrefix,
                          base::CompareCase::INSENSITIVE_ASCII);
}

bool IsOsScheme(std::string_view scheme) {
  return base::EqualsCaseInsensitiveASCII(scheme, kOsScheme);
}

}  // namespace gurl_os_handler_utils

}  // namespace crosapi