| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/web_applications/components/web_app_helpers.h" |
| |
| #include "base/base64.h" |
| #include "base/strings/strcat.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "components/crx_file/id_util.h" |
| #include "crypto/sha2.h" |
| #include "extensions/common/constants.h" |
| #include "url/gurl.h" |
| #include "url/url_constants.h" |
| |
| namespace web_app { |
| |
| namespace { |
| |
| // The following string is used to build the directory name for |
| // shortcuts to chrome applications (the kind which are installed |
| // from a CRX). Application shortcuts to URLs use the {host}_{path} |
| // for the name of this directory. Hosts can't include an underscore. |
| // By starting this string with an underscore, we ensure that there |
| // are no naming conflicts. |
| const char kCrxAppPrefix[] = "_crx_"; |
| |
| const char kFocusModePrefix[] = "_focus_"; |
| int64_t focus_mode_counter = 0; |
| |
| } // namespace |
| |
| std::string GenerateApplicationNameFromURL(const GURL& url) { |
| return base::StrCat({url.host_piece(), "_", url.path_piece()}); |
| } |
| |
| std::string GenerateApplicationNameFromAppId(const AppId& app_id) { |
| std::string t(kCrxAppPrefix); |
| t.append(app_id); |
| return t; |
| } |
| |
| // TODO(crbug.com/943194): Move this method to Focus Mode specific file. |
| // TODO(crbug.com/943653): Use site's manifest scope as window grouping key. |
| std::string GenerateApplicationNameForFocusMode() { |
| return kFocusModePrefix + base::NumberToString(focus_mode_counter++); |
| } |
| |
| AppId GetAppIdFromApplicationName(const std::string& app_name) { |
| std::string prefix(kCrxAppPrefix); |
| if (app_name.substr(0, prefix.length()) != prefix) |
| return std::string(); |
| return app_name.substr(prefix.length()); |
| } |
| |
| static std::string GenerateAppHashFromURL(const GURL& url) { |
| return crypto::SHA256HashString(url.spec()); |
| } |
| |
| AppId GenerateAppIdFromURL(const GURL& url) { |
| return crx_file::id_util::GenerateId(GenerateAppHashFromURL(url)); |
| } |
| |
| // Generate the public key for the fake extension that we synthesize to contain |
| // a web app. |
| // |
| // Web apps are not signed, but the public key for an extension doubles as |
| // its unique identity, and we need one of those. A web app's unique identity |
| // is its manifest URL, so we hash that (*) to create a public key. There will |
| // be no corresponding private key, which means that these extensions cannot be |
| // auto-updated using ExtensionUpdater. |
| // |
| // (*) The comment above says that we hash the manifest URL, but in practice, |
| // it seems that we hash the start URL. |
| std::string GenerateAppKeyFromURL(const GURL& url) { |
| std::string key; |
| base::Base64Encode(GenerateAppHashFromURL(url), &key); |
| return key; |
| } |
| |
| bool IsValidWebAppUrl(const GURL& app_url) { |
| if (app_url.is_empty() || app_url.inner_url()) |
| return false; |
| // kExtensionScheme is defined in extensions/common:common_constants. It's ok |
| // to depend on it. |
| return app_url.SchemeIs(url::kHttpScheme) || |
| app_url.SchemeIs(url::kHttpsScheme) || |
| app_url.SchemeIs(extensions::kExtensionScheme); |
| } |
| |
| bool IsValidExtensionUrl(const GURL& app_url) { |
| return !app_url.is_empty() && !app_url.inner_url() && |
| app_url.SchemeIs(extensions::kExtensionScheme); |
| } |
| |
| } // namespace web_app |