// Copyright (c) 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 "chrome/browser/notifications/web_page_notifier_controller.h"

#include "base/strings/utf_string_conversions.h"
#include "base/task/cancelable_task_tracker.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/favicon/favicon_service_factory.h"
#include "chrome/browser/notifications/desktop_notification_profile_util.h"
#include "chrome/browser/notifications/notifier_state_tracker.h"
#include "chrome/browser/notifications/notifier_state_tracker_factory.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/favicon/core/favicon_service.h"

WebPageNotifierController::WebPageNotifierController(Observer* observer)
    : observer_(observer) {}

WebPageNotifierController::~WebPageNotifierController() {}

std::vector<ash::mojom::NotifierUiDataPtr>
WebPageNotifierController::GetNotifierList(Profile* profile) {
  std::vector<ash::mojom::NotifierUiDataPtr> notifiers;

  ContentSettingsForOneType settings;
  DesktopNotificationProfileUtil::GetNotificationsSettings(profile, &settings);

  favicon::FaviconService* const favicon_service =
      FaviconServiceFactory::GetForProfile(profile,
                                           ServiceAccessType::EXPLICIT_ACCESS);
  favicon_tracker_.reset(new base::CancelableTaskTracker());
  patterns_.clear();
  for (ContentSettingsForOneType::const_iterator iter = settings.begin();
       iter != settings.end(); ++iter) {
    if (iter->primary_pattern == ContentSettingsPattern::Wildcard() &&
        iter->secondary_pattern == ContentSettingsPattern::Wildcard() &&
        iter->source != "preference") {
      continue;
    }

    std::string url_pattern = iter->primary_pattern.ToString();
    base::string16 name = base::UTF8ToUTF16(url_pattern);
    GURL url(url_pattern);
    message_center::NotifierId notifier_id(url);
    NotifierStateTracker* const notifier_state_tracker =
        NotifierStateTrackerFactory::GetForProfile(profile);
    content_settings::SettingInfo info;
    HostContentSettingsMapFactory::GetForProfile(profile)->GetWebsiteSetting(
        url, GURL(), CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string(), &info);
    notifiers.push_back(ash::mojom::NotifierUiData::New(
        notifier_id, name, false /* has_advanced_settings */,
        notifier_state_tracker->IsNotifierEnabled(notifier_id),
        info.source == content_settings::SETTING_SOURCE_POLICY,
        gfx::ImageSkia()));
    patterns_[url_pattern] = iter->primary_pattern;
    // Note that favicon service obtains the favicon from history. This means
    // that it will fail to obtain the image if there are no history data for
    // that URL.
    favicon_service->GetFaviconImageForPageURL(
        url,
        base::Bind(&WebPageNotifierController::OnFaviconLoaded,
                   base::Unretained(this), url),
        favicon_tracker_.get());
  }

  return notifiers;
}

void WebPageNotifierController::SetNotifierEnabled(
    Profile* profile,
    const message_center::NotifierId& notifier_id,
    bool enabled) {
  // WEB_PAGE notifier cannot handle in DesktopNotificationService
  // since it has the exact URL pattern.
  // TODO(mukai): fix this.
  ContentSetting default_setting =
      HostContentSettingsMapFactory::GetForProfile(profile)
          ->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS, NULL);

  DCHECK(default_setting == CONTENT_SETTING_ALLOW ||
         default_setting == CONTENT_SETTING_BLOCK ||
         default_setting == CONTENT_SETTING_ASK);

  // The content setting for notifications needs to clear when it changes to
  // the default value or get explicitly set when it differs from the
  // default.
  bool differs_from_default_value =
      (default_setting != CONTENT_SETTING_ALLOW && enabled) ||
      (default_setting == CONTENT_SETTING_ALLOW && !enabled);

  if (differs_from_default_value) {
    if (notifier_id.url.is_valid()) {
      if (enabled) {
        DesktopNotificationProfileUtil::GrantPermission(profile,
                                                        notifier_id.url);
      } else {
        DesktopNotificationProfileUtil::DenyPermission(profile,
                                                       notifier_id.url);
      }
    } else {
      LOG(ERROR) << "Invalid url pattern: "
                 << notifier_id.url.possibly_invalid_spec();
    }
  } else {
    ContentSettingsPattern pattern;

    const auto& iter = patterns_.find(notifier_id.url.possibly_invalid_spec());
    if (iter != patterns_.end()) {
      pattern = iter->second;
    } else if (notifier_id.url.is_valid()) {
      pattern = ContentSettingsPattern::FromURLNoWildcard(notifier_id.url);
    } else {
      LOG(ERROR) << "Invalid url pattern: "
                 << notifier_id.url.possibly_invalid_spec();
    }

    if (pattern.IsValid()) {
      // Note that we don't use
      // DesktopNotificationProfileUtil::ClearSetting()
      // here because pattern might be from user manual input and not match
      // the default one used by ClearSetting().
      HostContentSettingsMapFactory::GetForProfile(profile)
          ->SetContentSettingCustomScope(
              pattern, ContentSettingsPattern::Wildcard(),
              CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
              content_settings::ResourceIdentifier(), CONTENT_SETTING_DEFAULT);
    }
  }

  observer_->OnNotifierEnabledChanged(notifier_id, enabled);
}

void WebPageNotifierController::OnFaviconLoaded(
    const GURL& url,
    const favicon_base::FaviconImageResult& favicon_result) {
  observer_->OnIconImageUpdated(message_center::NotifierId(url),
                                favicon_result.image.AsImageSkia());
}
