// Copyright 2015 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 "components/background_sync/background_sync_controller_impl.h"

#include "base/containers/contains.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/keep_alive_registry/keep_alive_registry.h"
#include "components/variations/variations_associated_data.h"
#include "content/public/browser/background_sync_context.h"
#include "content/public/browser/background_sync_controller.h"
#include "content/public/browser/background_sync_parameters.h"
#include "content/public/browser/background_sync_registration.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/storage_partition.h"
#include "url/gurl.h"
#include "url/origin.h"

// static
const char BackgroundSyncControllerImpl::kFieldTrialName[] = "BackgroundSync";
const char BackgroundSyncControllerImpl::kDisabledParameterName[] = "disabled";
#if defined(OS_ANDROID)
const char BackgroundSyncControllerImpl::kRelyOnAndroidNetworkDetection[] =
    "rely_on_android_network_detection";
#endif
const char BackgroundSyncControllerImpl::kKeepBrowserAwakeParameterName[] =
    "keep_browser_awake_till_events_complete";
const char BackgroundSyncControllerImpl::kSkipPermissionsCheckParameterName[] =
    "skip_permissions_check_for_testing";
const char BackgroundSyncControllerImpl::kMaxAttemptsParameterName[] =
    "max_sync_attempts";
const char BackgroundSyncControllerImpl::
    kMaxAttemptsWithNotificationPermissionParameterName[] =
        "max_sync_attempts_with_notification_permission";
const char BackgroundSyncControllerImpl::kInitialRetryParameterName[] =
    "initial_retry_delay_sec";
const char BackgroundSyncControllerImpl::kRetryDelayFactorParameterName[] =
    "retry_delay_factor";
const char BackgroundSyncControllerImpl::kMinSyncRecoveryTimeName[] =
    "min_recovery_time_sec";
const char BackgroundSyncControllerImpl::kMaxSyncEventDurationName[] =
    "max_sync_event_duration_sec";
const char BackgroundSyncControllerImpl::kMinPeriodicSyncEventsInterval[] =
    "min_periodic_sync_events_interval_sec";

BackgroundSyncControllerImpl::BackgroundSyncControllerImpl(
    content::BrowserContext* browser_context,
    std::unique_ptr<background_sync::BackgroundSyncDelegate> delegate)
    : browser_context_(browser_context), delegate_(std::move(delegate)) {
  DCHECK(browser_context_);
  DCHECK(delegate_);

  background_sync_metrics_ =
      std::make_unique<BackgroundSyncMetrics>(delegate_.get());
  delegate_->GetHostContentSettingsMap()->AddObserver(this);
}

BackgroundSyncControllerImpl::~BackgroundSyncControllerImpl() = default;

void BackgroundSyncControllerImpl::OnContentSettingChanged(
    const ContentSettingsPattern& primary_pattern,
    const ContentSettingsPattern& secondary_pattern,
    ContentSettingsTypeSet content_type_set) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  if (!content_type_set.Contains(ContentSettingsType::BACKGROUND_SYNC) &&
      !content_type_set.Contains(
          ContentSettingsType::PERIODIC_BACKGROUND_SYNC)) {
    return;
  }

  std::vector<url::Origin> affected_origins;
  for (const auto& origin : periodic_sync_origins_) {
    if (!IsContentSettingBlocked(origin))
      continue;

    auto* storage_partition = browser_context_->GetStoragePartitionForUrl(
        origin.GetURL(), /* can_create= */ false);
    if (!storage_partition)
      continue;

    auto* background_sync_context =
        storage_partition->GetBackgroundSyncContext();
    if (!background_sync_context)
      continue;

    background_sync_context->UnregisterPeriodicSyncForOrigin(origin);
    affected_origins.push_back(origin);
  }

  // Stop tracking affected origins.
  for (const auto& origin : affected_origins) {
    periodic_sync_origins_.erase(origin);
  }
}

void BackgroundSyncControllerImpl::GetParameterOverrides(
    content::BackgroundSyncParameters* parameters) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

#if defined(OS_ANDROID)
  if (delegate_->ShouldDisableBackgroundSync())
    parameters->disable = true;
#endif

  std::map<std::string, std::string> field_params;
  if (!variations::GetVariationParams(kFieldTrialName, &field_params))
    return;

  if (base::LowerCaseEqualsASCII(field_params[kDisabledParameterName],
                                 "true")) {
    parameters->disable = true;
  }

  if (base::LowerCaseEqualsASCII(field_params[kKeepBrowserAwakeParameterName],
                                 "true")) {
    parameters->keep_browser_awake_till_events_complete = true;
  }

  if (base::LowerCaseEqualsASCII(
          field_params[kSkipPermissionsCheckParameterName], "true")) {
    parameters->skip_permissions_check_for_testing = true;
  }

  if (base::Contains(field_params,
                     kMaxAttemptsWithNotificationPermissionParameterName)) {
    int max_attempts;
    if (base::StringToInt(
            field_params[kMaxAttemptsWithNotificationPermissionParameterName],
            &max_attempts)) {
      parameters->max_sync_attempts_with_notification_permission = max_attempts;
    }
  }

  if (base::Contains(field_params, kMaxAttemptsParameterName)) {
    int max_attempts;
    if (base::StringToInt(field_params[kMaxAttemptsParameterName],
                          &max_attempts)) {
      parameters->max_sync_attempts = max_attempts;
    }
  }

  if (base::Contains(field_params, kInitialRetryParameterName)) {
    int initial_retry_delay_sec;
    if (base::StringToInt(field_params[kInitialRetryParameterName],
                          &initial_retry_delay_sec)) {
      parameters->initial_retry_delay = base::Seconds(initial_retry_delay_sec);
    }
  }

  if (base::Contains(field_params, kRetryDelayFactorParameterName)) {
    int retry_delay_factor;
    if (base::StringToInt(field_params[kRetryDelayFactorParameterName],
                          &retry_delay_factor)) {
      parameters->retry_delay_factor = retry_delay_factor;
    }
  }

  if (base::Contains(field_params, kMinSyncRecoveryTimeName)) {
    int min_sync_recovery_time_sec;
    if (base::StringToInt(field_params[kMinSyncRecoveryTimeName],
                          &min_sync_recovery_time_sec)) {
      parameters->min_sync_recovery_time =
          base::Seconds(min_sync_recovery_time_sec);
    }
  }

  if (base::Contains(field_params, kMaxSyncEventDurationName)) {
    int max_sync_event_duration_sec;
    if (base::StringToInt(field_params[kMaxSyncEventDurationName],
                          &max_sync_event_duration_sec)) {
      parameters->max_sync_event_duration =
          base::Seconds(max_sync_event_duration_sec);
    }
  }

  if (base::Contains(field_params, kMinPeriodicSyncEventsInterval)) {
    int min_periodic_sync_events_interval_sec;
    if (base::StringToInt(field_params[kMinPeriodicSyncEventsInterval],
                          &min_periodic_sync_events_interval_sec)) {
      parameters->min_periodic_sync_events_interval =
          base::Seconds(min_periodic_sync_events_interval_sec);
    }
  }

#if defined(OS_ANDROID)
  // Check if the delegate explicitly disabled this feature.
  if (delegate_->ShouldDisableAndroidNetworkDetection()) {
    parameters->rely_on_android_network_detection = false;
  } else if (base::Contains(field_params, kRelyOnAndroidNetworkDetection)) {
    if (base::LowerCaseEqualsASCII(field_params[kRelyOnAndroidNetworkDetection],
                                   "true")) {
      parameters->rely_on_android_network_detection = true;
    }
  }
#endif

  return;
}

void BackgroundSyncControllerImpl::NotifyOneShotBackgroundSyncRegistered(
    const url::Origin& origin,
    bool can_fire,
    bool is_reregistered) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  background_sync_metrics_->MaybeRecordOneShotSyncRegistrationEvent(
      origin, can_fire, is_reregistered);
}

void BackgroundSyncControllerImpl::NotifyPeriodicBackgroundSyncRegistered(
    const url::Origin& origin,
    int min_interval,
    bool is_reregistered) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  background_sync_metrics_->MaybeRecordPeriodicSyncRegistrationEvent(
      origin, min_interval, is_reregistered);
}

void BackgroundSyncControllerImpl::NotifyOneShotBackgroundSyncCompleted(
    const url::Origin& origin,
    blink::ServiceWorkerStatusCode status_code,
    int num_attempts,
    int max_attempts) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  background_sync_metrics_->MaybeRecordOneShotSyncCompletionEvent(
      origin, status_code, num_attempts, max_attempts);
}

void BackgroundSyncControllerImpl::NotifyPeriodicBackgroundSyncCompleted(
    const url::Origin& origin,
    blink::ServiceWorkerStatusCode status_code,
    int num_attempts,
    int max_attempts) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  background_sync_metrics_->MaybeRecordPeriodicSyncEventCompletion(
      origin, status_code, num_attempts, max_attempts);
}

void BackgroundSyncControllerImpl::ScheduleBrowserWakeUpWithDelay(
    blink::mojom::BackgroundSyncType sync_type,
    base::TimeDelta delay) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  if (delegate_->IsProfileOffTheRecord())
    return;

#if defined(OS_ANDROID)
  delegate_->ScheduleBrowserWakeUpWithDelay(sync_type, delay);
#endif
}

void BackgroundSyncControllerImpl::CancelBrowserWakeup(
    blink::mojom::BackgroundSyncType sync_type) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  if (delegate_->IsProfileOffTheRecord())
    return;

#if defined(OS_ANDROID)
  delegate_->CancelBrowserWakeup(sync_type);
#endif
}

base::TimeDelta BackgroundSyncControllerImpl::SnapToMaxOriginFrequency(
    int64_t min_interval,
    int64_t min_gap_for_origin) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  DCHECK_GE(min_gap_for_origin, 0);
  DCHECK_GE(min_interval, 0);

  if (min_interval < min_gap_for_origin)
    return base::Milliseconds(min_gap_for_origin);
  if (min_interval % min_gap_for_origin == 0)
    return base::Milliseconds(min_interval);
  return base::Milliseconds((min_interval / min_gap_for_origin + 1) *
                            min_gap_for_origin);
}

base::TimeDelta BackgroundSyncControllerImpl::ApplyMinGapForOrigin(
    base::TimeDelta delay,
    base::TimeDelta time_till_next_scheduled_event_for_origin,
    base::TimeDelta min_gap_for_origin) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  if (time_till_next_scheduled_event_for_origin.is_max())
    return delay;

  if (delay <= time_till_next_scheduled_event_for_origin - min_gap_for_origin)
    return delay;

  if (delay <= time_till_next_scheduled_event_for_origin)
    return time_till_next_scheduled_event_for_origin;

  if (delay <= time_till_next_scheduled_event_for_origin + min_gap_for_origin)
    return time_till_next_scheduled_event_for_origin + min_gap_for_origin;

  return delay;
}

bool BackgroundSyncControllerImpl::IsContentSettingBlocked(
    const url::Origin& origin) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  auto* host_content_settings_map = delegate_->GetHostContentSettingsMap();
  DCHECK(host_content_settings_map);

  auto url = origin.GetURL();
  return CONTENT_SETTING_ALLOW != host_content_settings_map->GetContentSetting(
                                      /* primary_url= */ url,
                                      /* secondary_url= */ url,
                                      ContentSettingsType::BACKGROUND_SYNC);
}

void BackgroundSyncControllerImpl::Shutdown() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  delegate_->GetHostContentSettingsMap()->RemoveObserver(this);
  delegate_->Shutdown();
}

base::TimeDelta BackgroundSyncControllerImpl::GetNextEventDelay(
    const content::BackgroundSyncRegistration& registration,
    content::BackgroundSyncParameters* parameters,
    base::TimeDelta time_till_soonest_scheduled_event_for_origin) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(parameters);

  int num_attempts = registration.num_attempts();

  if (!num_attempts) {
    // First attempt.
    switch (registration.sync_type()) {
      case blink::mojom::BackgroundSyncType::ONE_SHOT:
        return base::TimeDelta();
      case blink::mojom::BackgroundSyncType::PERIODIC:
        int site_engagement_factor =
            delegate_->GetSiteEngagementPenalty(registration.origin().GetURL());
        if (!site_engagement_factor)
          return base::TimeDelta::Max();

        int64_t effective_gap_ms =
            site_engagement_factor *
            parameters->min_periodic_sync_events_interval.InMilliseconds();
        return ApplyMinGapForOrigin(
            SnapToMaxOriginFrequency(registration.options()->min_interval,
                                     effective_gap_ms),
            time_till_soonest_scheduled_event_for_origin,
            parameters->min_periodic_sync_events_interval);
    }
  }

  // After a sync event has been fired.
  DCHECK_LT(num_attempts, parameters->max_sync_attempts);
  return parameters->initial_retry_delay *
         pow(parameters->retry_delay_factor, num_attempts - 1);
}

std::unique_ptr<content::BackgroundSyncController::BackgroundSyncEventKeepAlive>
BackgroundSyncControllerImpl::CreateBackgroundSyncEventKeepAlive() {
#if defined(OS_ANDROID)
  // Not needed on Android.
  return nullptr;
#else
  return delegate_->CreateBackgroundSyncEventKeepAlive();
#endif
}

void BackgroundSyncControllerImpl::NoteSuspendedPeriodicSyncOrigins(
    std::set<url::Origin> suspended_origins) {
  delegate_->NoteSuspendedPeriodicSyncOrigins(std::move(suspended_origins));
}

void BackgroundSyncControllerImpl::NoteRegisteredPeriodicSyncOrigins(
    std::set<url::Origin> registered_origins) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  for (auto& origin : registered_origins)
    periodic_sync_origins_.insert(std::move(origin));
}

void BackgroundSyncControllerImpl::AddToTrackedOrigins(
    const url::Origin& origin) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  periodic_sync_origins_.insert(origin);
}

void BackgroundSyncControllerImpl::RemoveFromTrackedOrigins(
    const url::Origin& origin) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  periodic_sync_origins_.erase(origin);
}
