| // 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 <utility> |
| |
| #include "chrome/browser/web_applications/web_app_install_finalizer.h" |
| |
| #include "base/bind.h" |
| #include "base/callback.h" |
| #include "base/logging.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "chrome/browser/installable/installable_metrics.h" |
| #include "chrome/browser/web_applications/components/web_app_constants.h" |
| #include "chrome/browser/web_applications/components/web_app_helpers.h" |
| #include "chrome/browser/web_applications/web_app.h" |
| #include "chrome/browser/web_applications/web_app_icon_manager.h" |
| #include "chrome/browser/web_applications/web_app_registry_update.h" |
| #include "chrome/browser/web_applications/web_app_sync_bridge.h" |
| #include "chrome/common/web_application_info.h" |
| #include "content/public/browser/browser_thread.h" |
| |
| namespace web_app { |
| |
| namespace { |
| |
| // TODO(loyso): Call sites should specify Source explicitly as a part of |
| // AppTraits parameter object. |
| Source::Type InferSourceFromMetricsInstallSource( |
| WebappInstallSource install_source) { |
| switch (install_source) { |
| case WebappInstallSource::MENU_BROWSER_TAB: |
| case WebappInstallSource::MENU_CUSTOM_TAB: |
| case WebappInstallSource::AUTOMATIC_PROMPT_BROWSER_TAB: |
| case WebappInstallSource::AUTOMATIC_PROMPT_CUSTOM_TAB: |
| case WebappInstallSource::API_BROWSER_TAB: |
| case WebappInstallSource::API_CUSTOM_TAB: |
| case WebappInstallSource::DEVTOOLS: |
| case WebappInstallSource::MANAGEMENT_API: |
| case WebappInstallSource::AMBIENT_BADGE_BROWSER_TAB: |
| case WebappInstallSource::AMBIENT_BADGE_CUSTOM_TAB: |
| case WebappInstallSource::OMNIBOX_INSTALL_ICON: |
| case WebappInstallSource::SYNC: |
| return Source::kSync; |
| |
| case WebappInstallSource::INTERNAL_DEFAULT: |
| case WebappInstallSource::EXTERNAL_DEFAULT: |
| return Source::kDefault; |
| |
| case WebappInstallSource::EXTERNAL_POLICY: |
| return Source::kPolicy; |
| |
| case WebappInstallSource::SYSTEM_DEFAULT: |
| return Source::kSystem; |
| |
| case WebappInstallSource::ARC: |
| return Source::kWebAppStore; |
| |
| case WebappInstallSource::COUNT: |
| NOTREACHED(); |
| return Source::kMaxValue; |
| } |
| } |
| |
| void SetIcons(const WebApplicationInfo& web_app_info, WebApp* web_app) { |
| WebApp::Icons web_app_icons; |
| |
| for (const WebApplicationInfo::IconInfo& icon_info : web_app_info.icons) { |
| // Skip unfetched bitmaps. |
| if (icon_info.data.colorType() == kUnknown_SkColorType) |
| continue; |
| |
| DCHECK_EQ(icon_info.width, icon_info.height); |
| |
| WebApp::IconInfo web_app_icon_info; |
| web_app_icon_info.url = icon_info.url; |
| web_app_icon_info.size_in_px = icon_info.width; |
| |
| web_app_icons.push_back(web_app_icon_info); |
| } |
| |
| web_app->SetIcons(std::move(web_app_icons)); |
| } |
| |
| } // namespace |
| |
| WebAppInstallFinalizer::WebAppInstallFinalizer(WebAppSyncBridge* sync_bridge, |
| WebAppIconManager* icon_manager) |
| : sync_bridge_(sync_bridge), icon_manager_(icon_manager) {} |
| |
| WebAppInstallFinalizer::~WebAppInstallFinalizer() = default; |
| |
| void WebAppInstallFinalizer::FinalizeInstall( |
| const WebApplicationInfo& web_app_info, |
| const FinalizeOptions& options, |
| InstallFinalizedCallback callback) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| |
| // TODO(loyso): Expose Source argument as a field of AppTraits struct. |
| const auto source = |
| InferSourceFromMetricsInstallSource(options.install_source); |
| |
| AppId app_id = GenerateAppIdFromURL(web_app_info.app_url); |
| // TODO(crbug.com/878262): Fix is_locally_installed flag handling here. |
| if (registrar().IsInstalled(app_id)) { |
| ScopedRegistryUpdate update(sync_bridge_); |
| WebApp* existing_web_app = update->UpdateApp(app_id); |
| existing_web_app->AddSource(source); |
| |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::BindOnce(std::move(callback), app_id, |
| InstallResultCode::kSuccessAlreadyInstalled)); |
| return; |
| } |
| |
| auto web_app = std::make_unique<WebApp>(app_id); |
| web_app->AddSource(source); |
| |
| web_app->SetName(base::UTF16ToUTF8(web_app_info.title)); |
| web_app->SetDescription(base::UTF16ToUTF8(web_app_info.description)); |
| web_app->SetLaunchUrl(web_app_info.app_url); |
| web_app->SetScope(web_app_info.scope); |
| web_app->SetThemeColor(web_app_info.theme_color); |
| web_app->SetLaunchContainer(web_app_info.open_as_window |
| ? LaunchContainer::kWindow |
| : LaunchContainer::kTab); |
| web_app->SetIsLocallyInstalled(options.locally_installed); |
| |
| SetIcons(web_app_info, web_app.get()); |
| |
| icon_manager_->WriteData( |
| std::move(app_id), std::make_unique<WebApplicationInfo>(web_app_info), |
| base::BindOnce(&WebAppInstallFinalizer::OnIconsDataWritten, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback), |
| std::move(web_app))); |
| } |
| |
| void WebAppInstallFinalizer::UninstallExternalWebApp( |
| const GURL& app_url, |
| UninstallWebAppCallback callback) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void WebAppInstallFinalizer::UninstallWebApp(const AppId& app_id, |
| UninstallWebAppCallback) { |
| // TODO(loyso): Implement The Unified Uninstall API. Expose Source as an |
| // argument for UninstallWebApp method. Do app->RemoveSource from the app and |
| // uninstall the app if no more sources interested. |
| NOTIMPLEMENTED(); |
| } |
| |
| void WebAppInstallFinalizer::OnIconsDataWritten( |
| InstallFinalizedCallback callback, |
| std::unique_ptr<WebApp> web_app, |
| bool success) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| if (!success) { |
| std::move(callback).Run(AppId(), InstallResultCode::kWriteDataFailed); |
| return; |
| } |
| |
| std::unique_ptr<WebAppRegistryUpdate> update = sync_bridge_->BeginUpdate(); |
| |
| AppId app_id = web_app->app_id(); |
| update->CreateApp(std::move(web_app)); |
| |
| sync_bridge_->CommitUpdate( |
| std::move(update), |
| base::BindOnce(&WebAppInstallFinalizer::OnDatabaseCommitCompleted, |
| weak_ptr_factory_.GetWeakPtr(), std::move(callback), |
| std::move(app_id))); |
| } |
| |
| void WebAppInstallFinalizer::OnDatabaseCommitCompleted( |
| InstallFinalizedCallback callback, |
| const AppId& app_id, |
| bool success) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| if (!success) { |
| std::move(callback).Run(AppId(), InstallResultCode::kWriteDataFailed); |
| return; |
| } |
| |
| registrar().NotifyWebAppInstalled(app_id); |
| std::move(callback).Run(app_id, InstallResultCode::kSuccessNewInstall); |
| } |
| |
| bool WebAppInstallFinalizer::CanCreateOsShortcuts() const { |
| // TODO(loyso): Implement it. |
| NOTIMPLEMENTED(); |
| return false; |
| } |
| |
| void WebAppInstallFinalizer::CreateOsShortcuts( |
| const AppId& app_id, |
| bool add_to_desktop, |
| CreateOsShortcutsCallback callback) { |
| // TODO(loyso): Implement it. |
| NOTIMPLEMENTED(); |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, |
| base::BindOnce(std::move(callback), false /* shortcuts_created */)); |
| } |
| |
| bool WebAppInstallFinalizer::CanRevealAppShim() const { |
| // TODO(loyso): Implement it. |
| NOTIMPLEMENTED(); |
| return false; |
| } |
| |
| void WebAppInstallFinalizer::RevealAppShim(const AppId& app_id) { |
| // TODO(loyso): Implement it. |
| NOTIMPLEMENTED(); |
| } |
| |
| bool WebAppInstallFinalizer::CanSkipAppUpdateForSync( |
| const AppId& app_id, |
| const WebApplicationInfo& web_app_info) const { |
| NOTIMPLEMENTED(); |
| return true; |
| } |
| |
| bool WebAppInstallFinalizer::CanUserUninstallFromSync( |
| const AppId& app_id) const { |
| // TODO(crbug.com/901226): Implement it. |
| return false; |
| } |
| |
| } // namespace web_app |