blob: 8ce405cc563adda96dc8ea29a9dfd64f7fe12dd9 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// 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/jobs/link_capturing.h"
#include "base/values.h"
#include "chrome/browser/web_applications/locks/all_apps_lock.h"
#include "chrome/browser/web_applications/proto/web_app.pb.h"
#include "chrome/browser/web_applications/proto/web_app_install_state.pb.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/browser/web_applications/web_app_registry_update.h"
#include "chrome/browser/web_applications/web_app_sync_bridge.h"
namespace web_app {
void SetAppCapturesSupportedLinksDisableOverlapping(
const webapps::AppId& app_id,
bool set_to_preferred,
AllAppsLock& lock,
base::Value::Dict& debug_value) {
debug_value.Set("app_id", app_id);
debug_value.Set("set_to_preferred", set_to_preferred);
if (!lock.registrar().IsInstallState(
app_id, {proto::INSTALLED_WITHOUT_OS_INTEGRATION,
proto::INSTALLED_WITH_OS_INTEGRATION})) {
debug_value.Set("result", "App not installed.");
return;
}
// When disabling, simply disable & exit because this doesn't need to affect
// the state of other apps.
if (!set_to_preferred) {
{
ScopedRegistryUpdate update = lock.sync_bridge().BeginUpdate();
WebApp* app_to_update = update->UpdateApp(app_id);
app_to_update->SetLinkCapturingUserPreference(
proto::NAVIGATION_CAPTURING_PREFERENCE_DO_NOT_CAPTURE);
}
debug_value.Set("app_updated", true);
// TODO(b/273830801): Automatically call observers when changes are
// committed to the web_app DB (here and below).
lock.registrar().NotifyWebAppUserLinkCapturingPreferencesChanged(
app_id, set_to_preferred);
return;
}
// Whe enabling, any app with the same scope (overlapping) that is explicitly
// enabled must be disabled to prevent multiple apps from capturing links on
// the same scope.
for (const webapps::AppId& other_app_id : lock.registrar().GetAppIds()) {
if (other_app_id == app_id) {
{
ScopedRegistryUpdate update = lock.sync_bridge().BeginUpdate();
WebApp* app_to_update = update->UpdateApp(app_id);
app_to_update->SetLinkCapturingUserPreference(
set_to_preferred
? proto::NAVIGATION_CAPTURING_PREFERENCE_CAPTURE
: proto::NAVIGATION_CAPTURING_PREFERENCE_DO_NOT_CAPTURE);
}
debug_value.Set("app_updated", true);
lock.registrar().NotifyWebAppUserLinkCapturingPreferencesChanged(
app_id, set_to_preferred);
continue;
}
if (!lock.registrar().CanCaptureLinksInScope(other_app_id)) {
continue;
}
if (!lock.registrar().AppScopesMatchForUserLinkCapturing(app_id,
other_app_id)) {
continue;
}
const WebApp* other_app = lock.registrar().GetAppById(other_app_id);
CHECK(other_app);
// Only update apps that are explicitly turned on. We want to leave any set
// as 'default' to stay as such, allowing them to take over if this one is
// uninstalled.
if (other_app->user_link_capturing_preference() !=
proto::NAVIGATION_CAPTURING_PREFERENCE_CAPTURE) {
continue;
}
{
ScopedRegistryUpdate update = lock.sync_bridge().BeginUpdate();
WebApp* app_to_update = update->UpdateApp(other_app_id);
app_to_update->SetLinkCapturingUserPreference(
proto::NAVIGATION_CAPTURING_PREFERENCE_DO_NOT_CAPTURE);
}
debug_value.EnsureList("capturing_apps_disabled")->Append(other_app_id);
lock.registrar().NotifyWebAppUserLinkCapturingPreferencesChanged(
other_app_id, /*is_preferred=*/false);
}
return;
}
} // namespace web_app