blob: cc979093e31a313482e60a2f6954948d55276d20 [file] [log] [blame]
// Copyright 2016 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 "third_party/blink/renderer/modules/installedapp/installed_app_controller.h"
#include <utility>
#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/blink/public/mojom/installedapp/related_application.mojom-blink.h"
#include "third_party/blink/public/mojom/manifest/manifest.mojom-blink.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/modules/manifest/manifest_manager.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
InstalledAppController::~InstalledAppController() = default;
void InstalledAppController::GetInstalledRelatedApps(
std::unique_ptr<AppInstalledCallbacks> callbacks) {
// When detached, the fetch logic is no longer valid.
if (!GetSupplementable()->GetFrame()) {
// TODO(mgiuca): AbortError rather than simply undefined.
// https://crbug.com/687846
callbacks->OnError();
return;
}
// Get the list of related applications from the manifest.
// Upon returning, filter the result list to those apps that are installed.
ManifestManager::From(*GetSupplementable())
->RequestManifest(
WTF::Bind(&InstalledAppController::OnGetManifestForRelatedApps,
WrapPersistent(this), std::move(callbacks)));
}
InstalledAppController* InstalledAppController::From(LocalDOMWindow& window) {
InstalledAppController* controller =
Supplement<LocalDOMWindow>::From<InstalledAppController>(window);
if (!controller) {
controller = MakeGarbageCollected<InstalledAppController>(window);
Supplement<LocalDOMWindow>::ProvideTo(window, controller);
}
return controller;
}
const char InstalledAppController::kSupplementName[] = "InstalledAppController";
InstalledAppController::InstalledAppController(LocalDOMWindow& window)
: Supplement<LocalDOMWindow>(window),
provider_(&window) {}
void InstalledAppController::OnGetManifestForRelatedApps(
std::unique_ptr<AppInstalledCallbacks> callbacks,
const KURL& url,
mojom::blink::ManifestPtr manifest) {
if (!GetSupplementable()->GetFrame()) {
callbacks->OnError();
return;
}
Vector<mojom::blink::RelatedApplicationPtr> mojo_related_apps;
for (const auto& related_application : manifest->related_applications) {
auto application = mojom::blink::RelatedApplication::New();
application->platform = related_application->platform;
application->id = related_application->id;
if (related_application->url.has_value())
application->url = related_application->url->GetString();
mojo_related_apps.push_back(std::move(application));
}
if (!provider_.is_bound()) {
// See https://bit.ly/2S0zRAS for task types.
GetSupplementable()->GetBrowserInterfaceBroker().GetInterface(
provider_.BindNewPipeAndPassReceiver(
GetSupplementable()->GetTaskRunner(TaskType::kMiscPlatformAPI)));
// TODO(mgiuca): Set a connection error handler. This requires a refactor to
// work like NavigatorShare.cpp (retain a persistent list of clients to
// reject all of their promises).
DCHECK(provider_.is_bound());
}
provider_->FilterInstalledApps(
std::move(mojo_related_apps), url,
WTF::Bind(&InstalledAppController::OnFilterInstalledApps,
WrapPersistent(this), std::move(callbacks)));
}
void InstalledAppController::OnFilterInstalledApps(
std::unique_ptr<AppInstalledCallbacks> callbacks,
Vector<mojom::blink::RelatedApplicationPtr> result) {
HeapVector<Member<RelatedApplication>> applications;
for (const auto& res : result) {
auto* app = RelatedApplication::Create();
app->setPlatform(res->platform);
if (!res->url.IsNull())
app->setUrl(res->url);
if (!res->id.IsNull())
app->setId(res->id);
if (!res->version.IsNull())
app->setVersion(res->version);
applications.push_back(app);
}
LocalDOMWindow* window = GetSupplementable();
ukm::builders::InstalledRelatedApps(window->UkmSourceID())
.SetCalled(true)
.Record(window->UkmRecorder());
callbacks->OnSuccess(applications);
}
void InstalledAppController::Trace(Visitor* visitor) const {
visitor->Trace(provider_);
Supplement<LocalDOMWindow>::Trace(visitor);
}
} // namespace blink