// Copyright 2014 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 <set>

#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_storage_monitor.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/ui/extensions/application_launch.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_system.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/message_center_observer.h"

namespace extensions {

namespace {

const int kInitialUsageThreshold = 500;

const char kWriteDataApp[] = "storage_monitor/write_data";

class NotificationObserver : public message_center::MessageCenterObserver {
 public:
  explicit NotificationObserver(const std::string& target_notification)
      : message_center_(message_center::MessageCenter::Get()),
        target_notification_id_(target_notification),
        waiting_(false) {
    message_center_->AddObserver(this);
  }

  virtual ~NotificationObserver() {
    message_center_->RemoveObserver(this);
  }

  bool HasReceivedNotification() const {
    return received_notifications_.find(target_notification_id_) !=
      received_notifications_.end();
  }

  // Runs the message loop and returns true if a notification is received.
  // Immediately returns true if a notification has already been received.
  bool WaitForNotification() {
    if (HasReceivedNotification())
      return true;

    waiting_ = true;
    content::RunMessageLoop();
    waiting_ = false;
    return HasReceivedNotification();
  }

 private:
  // MessageCenterObserver implementation:
  virtual void OnNotificationAdded(
      const std::string& notification_id) OVERRIDE {
    received_notifications_.insert(notification_id);

    if (waiting_ && HasReceivedNotification())
      base::MessageLoopForUI::current()->Quit();
  }

  message_center::MessageCenter* message_center_;
  std::set<std::string> received_notifications_;
  std::string target_notification_id_;
  bool waiting_;
};

}  // namespace

class ExtensionStorageMonitorTest : public ExtensionBrowserTest {
 public:
  ExtensionStorageMonitorTest() : storage_monitor_(NULL) {}

 protected:
  // ExtensionBrowserTest overrides:
  virtual void SetUpOnMainThread() OVERRIDE {
    ExtensionBrowserTest::SetUpOnMainThread();

    InitStorageMonitor();
  }

  ExtensionStorageMonitor* monitor() {
    CHECK(storage_monitor_);
    return storage_monitor_;
  }

  int64 GetInitialExtensionThreshold() {
    CHECK(storage_monitor_);
    return storage_monitor_->initial_extension_threshold_;
  }

  int64 GetInitialEphemeralThreshold() {
    CHECK(storage_monitor_);
    return storage_monitor_->initial_ephemeral_threshold_;
  }

  void DisableForInstalledExtensions() {
    CHECK(storage_monitor_);
    storage_monitor_->enable_for_all_extensions_ = false;
  }

  const Extension* InitWriteDataApp() {
    base::FilePath path = test_data_dir_.AppendASCII(kWriteDataApp);
    const Extension* extension = InstallExtension(path, 1);
    EXPECT_TRUE(extension);
    return extension;
  }

  const Extension* InitWriteDataEphemeralApp() {
    // The threshold for installed extensions should be higher than ephemeral
    // apps.
    storage_monitor_->initial_extension_threshold_ =
        storage_monitor_->initial_ephemeral_threshold_ * 4;

    base::FilePath path = test_data_dir_.AppendASCII(kWriteDataApp);
    const Extension* extension = InstallEphemeralAppWithSourceAndFlags(
        path, 1, Manifest::INTERNAL, Extension::NO_FLAGS);
    EXPECT_TRUE(extension);
    return extension;
  }

  std::string GetNotificationId(const std::string& extension_id) {
    return monitor()->GetNotificationId(extension_id);
  }

  bool IsStorageNotificationEnabled(const std::string& extension_id) {
    return monitor()->IsStorageNotificationEnabled(extension_id);
  }

  int64 GetNextStorageThreshold(const std::string& extension_id) {
    return monitor()->GetNextStorageThreshold(extension_id);
  }

  void WriteBytesExpectingNotification(const Extension* extension,
                                       int num_bytes) {
    int64 previous_threshold = GetNextStorageThreshold(extension->id());
    WriteBytes(extension, num_bytes, true);
    EXPECT_GT(GetNextStorageThreshold(extension->id()), previous_threshold);
  }

  void WriteBytesNotExpectingNotification(const Extension* extension,
                                         int num_bytes) {
    WriteBytes(extension, num_bytes, false);
  }

  void SimulateUninstallDialogAccept() {
    // Ensure the uninstall dialog was shown and fake an accept.
    ASSERT_TRUE(monitor()->uninstall_dialog_.get());
    monitor()->ExtensionUninstallAccepted();
  }

 private:
  void InitStorageMonitor() {
    storage_monitor_ = ExtensionStorageMonitor::Get(profile());
    ASSERT_TRUE(storage_monitor_);

    // Override thresholds so that we don't have to write a huge amount of data
    // to trigger notifications in these tests.
    storage_monitor_->enable_for_all_extensions_ = true;
    storage_monitor_->initial_extension_threshold_ = kInitialUsageThreshold;
    storage_monitor_->initial_ephemeral_threshold_ = kInitialUsageThreshold;

    // To ensure storage events are dispatched from QuotaManager immediately.
    storage_monitor_->observer_rate_ = 0;
  }

  // Write a number of bytes to persistent storage.
  void WriteBytes(const Extension* extension,
                  int num_bytes,
                  bool expected_notification) {
    ExtensionTestMessageListener launched_listener("launched", true);
    ExtensionTestMessageListener write_complete_listener(
        "write_complete", false);
    NotificationObserver notification_observer(
        GetNotificationId(extension->id()));

    OpenApplication(AppLaunchParams(
        profile(), extension, LAUNCH_CONTAINER_NONE, NEW_WINDOW));
    ASSERT_TRUE(launched_listener.WaitUntilSatisfied());

    // Instruct the app to write |num_bytes| of data.
    launched_listener.Reply(base::IntToString(num_bytes));
    ASSERT_TRUE(write_complete_listener.WaitUntilSatisfied());

    if (expected_notification) {
      EXPECT_TRUE(notification_observer.WaitForNotification());
    } else {
      base::RunLoop().RunUntilIdle();
      EXPECT_FALSE(notification_observer.HasReceivedNotification());
    }
  }

  ExtensionStorageMonitor* storage_monitor_;
};

// Control - No notifications should be shown if usage remains under the
// threshold.
IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, UnderThreshold) {
  const Extension* extension = InitWriteDataApp();
  ASSERT_TRUE(extension);
  WriteBytesNotExpectingNotification(extension, 1);
}

// Ensure a notification is shown when usage reaches the first threshold.
IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, ExceedInitialThreshold) {
  const Extension* extension = InitWriteDataApp();
  ASSERT_TRUE(extension);
  WriteBytesExpectingNotification(extension, GetInitialExtensionThreshold());
}

// Ensure a notification is shown when usage immediately exceeds double the
// first threshold.
IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, DoubleInitialThreshold) {
  const Extension* extension = InitWriteDataApp();
  ASSERT_TRUE(extension);
  WriteBytesExpectingNotification(extension,
                                  GetInitialExtensionThreshold() * 2);
}

// Ensure that notifications are not fired if the next threshold has not been
// reached.
IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, ThrottleNotifications) {
  const Extension* extension = InitWriteDataApp();
  ASSERT_TRUE(extension);

  // Exceed the first threshold.
  WriteBytesExpectingNotification(extension, GetInitialExtensionThreshold());

  // Stay within the next threshold.
  WriteBytesNotExpectingNotification(extension, 1);
}

// Verify that notifications are disabled when the user clicks the action button
// in the notification.
IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, UserDisabledNotifications) {
  const Extension* extension = InitWriteDataApp();
  ASSERT_TRUE(extension);
  WriteBytesExpectingNotification(extension, GetInitialExtensionThreshold());

  EXPECT_TRUE(IsStorageNotificationEnabled(extension->id()));

  // Fake clicking the notification button to disable notifications.
  message_center::MessageCenter::Get()->ClickOnNotificationButton(
      GetNotificationId(extension->id()),
      ExtensionStorageMonitor::BUTTON_DISABLE_NOTIFICATION);

  EXPECT_FALSE(IsStorageNotificationEnabled(extension->id()));

  // Expect to receive no further notifications when usage continues to
  // increase.
  int64 next_threshold = GetNextStorageThreshold(extension->id());
  int64 next_data_size = next_threshold - GetInitialExtensionThreshold();
  ASSERT_GT(next_data_size, 0);

  WriteBytesNotExpectingNotification(extension, next_data_size);
}

// Verify that thresholds for ephemeral apps are reset when they are
// promoted to regular installed apps.
IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, EphemeralAppLowUsage) {
  const Extension* extension = InitWriteDataEphemeralApp();
  ASSERT_TRUE(extension);
  WriteBytesExpectingNotification(extension, GetInitialEphemeralThreshold());

  // Store the number of bytes until the next threshold is reached.
  int64 next_threshold = GetNextStorageThreshold(extension->id());
  int64 next_data_size = next_threshold - GetInitialEphemeralThreshold();
  ASSERT_GT(next_data_size, 0);
  EXPECT_GE(GetInitialExtensionThreshold(), next_threshold);

  // Promote the ephemeral app.
  ExtensionService* service =
      ExtensionSystem::Get(profile())->extension_service();
  service->PromoteEphemeralApp(extension, false);

  // The next threshold should now be equal to the initial threshold for
  // extensions (which is higher than the initial threshold for ephemeral apps).
  EXPECT_EQ(GetInitialExtensionThreshold(),
            GetNextStorageThreshold(extension->id()));

  // Since the threshold was increased, a notification should not be
  // triggered.
  WriteBytesNotExpectingNotification(extension, next_data_size);
}

// Verify that thresholds for ephemeral apps are not reset when they are
// promoted to regular installed apps if their usage is higher than the initial
// threshold for installed extensions.
IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, EphemeralAppWithHighUsage) {
  const Extension* extension = InitWriteDataEphemeralApp();
  ASSERT_TRUE(extension);
  WriteBytesExpectingNotification(extension, GetInitialExtensionThreshold());
  int64 saved_next_threshold = GetNextStorageThreshold(extension->id());

  // Promote the ephemeral app.
  ExtensionService* service =
      ExtensionSystem::Get(profile())->extension_service();
  service->PromoteEphemeralApp(extension, false);

  // The next threshold should not have changed.
  EXPECT_EQ(saved_next_threshold, GetNextStorageThreshold(extension->id()));
}

// Ensure that monitoring is disabled for installed extensions if
// |enable_for_all_extensions_| is false. This test can be removed if monitoring
// is eventually enabled for all extensions.
IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest,
                       DisableForInstalledExtensions) {
  DisableForInstalledExtensions();

  const Extension* extension = InitWriteDataApp();
  ASSERT_TRUE(extension);
  WriteBytesNotExpectingNotification(extension, GetInitialExtensionThreshold());
}

// Verify that notifications are disabled when the user clicks the action button
// in the notification.
IN_PROC_BROWSER_TEST_F(ExtensionStorageMonitorTest, UninstallExtension) {
  const Extension* extension = InitWriteDataApp();
  ASSERT_TRUE(extension);
  WriteBytesExpectingNotification(extension, GetInitialExtensionThreshold());

  // Fake clicking the notification button to uninstall.
  message_center::MessageCenter::Get()->ClickOnNotificationButton(
      GetNotificationId(extension->id()),
      ExtensionStorageMonitor::BUTTON_UNINSTALL);

  // Also fake accepting the uninstall.
  content::WindowedNotificationObserver uninstalled_signal(
      chrome::NOTIFICATION_EXTENSION_UNINSTALLED_DEPRECATED,
      content::Source<Profile>(profile()));
  SimulateUninstallDialogAccept();
  uninstalled_signal.Wait();
}

}  // namespace extensions
