| // 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_shortcut.h" | 
 |  | 
 | #include <functional> | 
 |  | 
 | #include "base/bind.h" | 
 | #include "base/i18n/file_util_icu.h" | 
 | #include "base/strings/utf_string_conversions.h" | 
 | #include "base/task/post_task.h" | 
 | #include "build/build_config.h" | 
 | #include "chrome/browser/web_applications/components/web_app_helpers.h" | 
 | #include "chrome/common/chrome_constants.h" | 
 | #include "content/public/browser/browser_thread.h" | 
 |  | 
 | using content::BrowserThread; | 
 |  | 
 | namespace { | 
 |  | 
 | void DeleteShortcutInfoOnUIThread( | 
 |     std::unique_ptr<web_app::ShortcutInfo> shortcut_info, | 
 |     base::OnceClosure callback) { | 
 |   shortcut_info.reset(); | 
 |   if (callback) | 
 |     std::move(callback).Run(); | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | namespace web_app { | 
 |  | 
 | ShortcutInfo::ShortcutInfo() = default; | 
 |  | 
 | ShortcutInfo::~ShortcutInfo() { | 
 |   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 
 | } | 
 |  | 
 | ShortcutLocations::ShortcutLocations() | 
 |     : on_desktop(false), | 
 |       applications_menu_location(APP_MENU_LOCATION_NONE), | 
 |       in_quick_launch_bar(false) {} | 
 |  | 
 | std::string GenerateApplicationNameFromInfo(const ShortcutInfo& shortcut_info) { | 
 |   // TODO(loyso): Remove this empty()/non-empty difference. | 
 |   if (shortcut_info.extension_id.empty()) | 
 |     return GenerateApplicationNameFromURL(shortcut_info.url); | 
 |  | 
 |   return GenerateApplicationNameFromAppId(shortcut_info.extension_id); | 
 | } | 
 |  | 
 | base::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path, | 
 |                                       const std::string& extension_id, | 
 |                                       const GURL& url) { | 
 |   DCHECK(!profile_path.empty()); | 
 |   base::FilePath app_data_dir(profile_path.Append(chrome::kWebAppDirname)); | 
 |  | 
 |   if (!extension_id.empty()) { | 
 |     return app_data_dir.AppendASCII( | 
 |         GenerateApplicationNameFromAppId(extension_id)); | 
 |   } | 
 |  | 
 |   std::string host(url.host()); | 
 |   std::string scheme(url.has_scheme() ? url.scheme() : "http"); | 
 |   std::string port(url.has_port() ? url.port() : "80"); | 
 |   std::string scheme_port(scheme + "_" + port); | 
 |  | 
 | #if defined(OS_WIN) | 
 |   base::FilePath::StringType host_path(base::UTF8ToUTF16(host)); | 
 |   base::FilePath::StringType scheme_port_path(base::UTF8ToUTF16(scheme_port)); | 
 | #elif defined(OS_POSIX) | 
 |   base::FilePath::StringType host_path(host); | 
 |   base::FilePath::StringType scheme_port_path(scheme_port); | 
 | #endif | 
 |  | 
 |   return app_data_dir.Append(host_path).Append(scheme_port_path); | 
 | } | 
 |  | 
 | namespace internals { | 
 |  | 
 | void PostShortcutIOTask(base::OnceCallback<void(const ShortcutInfo&)> task, | 
 |                         std::unique_ptr<ShortcutInfo> shortcut_info) { | 
 |   PostShortcutIOTaskAndReply(std::move(task), std::move(shortcut_info), | 
 |                              base::OnceClosure()); | 
 | } | 
 |  | 
 | void PostShortcutIOTaskAndReply( | 
 |     base::OnceCallback<void(const ShortcutInfo&)> task, | 
 |     std::unique_ptr<ShortcutInfo> shortcut_info, | 
 |     base::OnceClosure reply) { | 
 |   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
 |  | 
 |   // Ownership of |shortcut_info| moves to the Reply, which is guaranteed to | 
 |   // outlive the const reference. | 
 |   const web_app::ShortcutInfo& shortcut_info_ref = *shortcut_info; | 
 |   GetShortcutIOTaskRunner()->PostTaskAndReply( | 
 |       FROM_HERE, base::BindOnce(std::move(task), std::cref(shortcut_info_ref)), | 
 |       base::BindOnce(&DeleteShortcutInfoOnUIThread, std::move(shortcut_info), | 
 |                      std::move(reply))); | 
 | } | 
 |  | 
 | scoped_refptr<base::TaskRunner> GetShortcutIOTaskRunner() { | 
 |   constexpr base::TaskTraits traits = { | 
 |       base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT, | 
 |       base::TaskShutdownBehavior::BLOCK_SHUTDOWN}; | 
 |  | 
 | #if defined(OS_WIN) | 
 |   return base::CreateCOMSTATaskRunner( | 
 |       traits, base::SingleThreadTaskRunnerThreadMode::SHARED); | 
 | #else | 
 |   return base::CreateTaskRunner(traits); | 
 | #endif | 
 | } | 
 |  | 
 | base::FilePath GetSanitizedFileName(const base::string16& name) { | 
 | #if defined(OS_WIN) | 
 |   base::string16 file_name = name; | 
 | #else | 
 |   std::string file_name = base::UTF16ToUTF8(name); | 
 | #endif | 
 |   base::i18n::ReplaceIllegalCharactersInPath(&file_name, '_'); | 
 |   return base::FilePath(file_name); | 
 | } | 
 |  | 
 | base::FilePath GetShortcutDataDir(const web_app::ShortcutInfo& shortcut_info) { | 
 |   return web_app::GetWebAppDataDirectory(shortcut_info.profile_path, | 
 |                                          shortcut_info.extension_id, | 
 |                                          shortcut_info.url); | 
 | } | 
 |  | 
 | }  // namespace internals | 
 |  | 
 | }  // namespace web_app |