blob: 70cc13a2174e034fba5cc1644a1a2a2f8f1fdf31 [file] [log] [blame]
// 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_data_retriever.h"
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/callback.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/installable/installable_data.h"
#include "chrome/browser/installable/installable_manager.h"
#include "chrome/browser/web_applications/components/web_app_icon_downloader.h"
#include "chrome/browser/web_applications/components/web_app_icon_generator.h"
#include "chrome/common/chrome_render_frame.mojom.h"
#include "chrome/common/web_application_info.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/skia/include/core/SkColor.h"
namespace web_app {
WebAppDataRetriever::WebAppDataRetriever() = default;
WebAppDataRetriever::~WebAppDataRetriever() = default;
void WebAppDataRetriever::GetWebApplicationInfo(
content::WebContents* web_contents,
GetWebApplicationInfoCallback callback) {
// Concurrent calls are not allowed.
CHECK(!get_web_app_info_callback_);
get_web_app_info_callback_ = std::move(callback);
content::NavigationEntry* entry =
web_contents->GetController().GetLastCommittedEntry();
if (!entry) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(std::move(get_web_app_info_callback_), nullptr));
return;
}
chrome::mojom::ChromeRenderFrameAssociatedPtr chrome_render_frame;
web_contents->GetMainFrame()->GetRemoteAssociatedInterfaces()->GetInterface(
&chrome_render_frame);
// Set the error handler so that we can run |get_web_app_info_callback_| if
// the WebContents or the RenderFrameHost are destroyed and the connection
// to ChromeRenderFrame is lost.
chrome_render_frame.set_connection_error_handler(
base::BindOnce(&WebAppDataRetriever::OnGetWebApplicationInfoFailed,
weak_ptr_factory_.GetWeakPtr()));
// Bind the InterfacePtr into the callback so that it's kept alive
// until there's either a connection error or a response.
auto* web_app_info_proxy = chrome_render_frame.get();
web_app_info_proxy->GetWebApplicationInfo(base::BindOnce(
&WebAppDataRetriever::OnGetWebApplicationInfo,
weak_ptr_factory_.GetWeakPtr(), std::move(chrome_render_frame),
web_contents, entry->GetUniqueID()));
}
void WebAppDataRetriever::CheckInstallabilityAndRetrieveManifest(
content::WebContents* web_contents,
CheckInstallabilityCallback callback) {
InstallableManager* installable_manager =
InstallableManager::FromWebContents(web_contents);
DCHECK(installable_manager);
// TODO(crbug.com/829232) Unify with other calls to GetData.
InstallableParams params;
params.check_eligibility = true;
params.valid_primary_icon = true;
params.valid_manifest = true;
params.has_worker = true;
// Do not wait_for_worker. OnDidPerformInstallableCheck is always invoked.
installable_manager->GetData(
params, base::BindRepeating(
&WebAppDataRetriever::OnDidPerformInstallableCheck,
weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback)));
}
void WebAppDataRetriever::GetIcons(content::WebContents* web_contents,
const std::vector<GURL>& icon_urls,
bool skip_page_fav_icons,
GetIconsCallback callback) {
DCHECK(!icon_urls.empty());
// TODO(loyso): Refactor WebAppIconDownloader: crbug.com/907296.
icon_downloader_ = std::make_unique<WebAppIconDownloader>(
web_contents, icon_urls, "WebApp.Icon.HttpStatusCodeClassOnCreate",
base::BindOnce(&WebAppDataRetriever::OnIconsDownloaded,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
if (skip_page_fav_icons)
icon_downloader_->SkipPageFavicons();
icon_downloader_->Start();
}
void WebAppDataRetriever::OnGetWebApplicationInfo(
chrome::mojom::ChromeRenderFrameAssociatedPtr chrome_render_frame,
content::WebContents* web_contents,
int last_committed_nav_entry_unique_id,
const WebApplicationInfo& web_app_info) {
content::NavigationEntry* entry =
web_contents->GetController().GetLastCommittedEntry();
if (!entry || last_committed_nav_entry_unique_id != entry->GetUniqueID()) {
std::move(get_web_app_info_callback_).Run(nullptr);
return;
}
auto info = std::make_unique<WebApplicationInfo>(web_app_info);
if (info->app_url.is_empty())
info->app_url = web_contents->GetLastCommittedURL();
if (info->title.empty())
info->title = web_contents->GetTitle();
if (info->title.empty())
info->title = base::UTF8ToUTF16(info->app_url.spec());
std::move(get_web_app_info_callback_).Run(std::move(info));
}
void WebAppDataRetriever::OnGetWebApplicationInfoFailed() {
std::move(get_web_app_info_callback_).Run(nullptr);
}
void WebAppDataRetriever::OnDidPerformInstallableCheck(
CheckInstallabilityCallback callback,
const InstallableData& data) {
DCHECK(data.manifest_url.is_valid() || data.manifest->IsEmpty());
const bool is_installable = data.errors.empty();
std::move(callback).Run(*data.manifest, is_installable);
}
void WebAppDataRetriever::OnIconsDownloaded(GetIconsCallback callback,
bool success,
const IconsMap& icons_map) {
// |icons_map| is owned by |icon_downloader_|. Take a copy before destroying
// the downloader. Return empty |result_map| if the tab has navigated away
// during the icon download.
IconsMap result_map;
if (success)
result_map = icons_map;
icon_downloader_.reset();
std::move(callback).Run(std::move(result_map));
}
} // namespace web_app