// Copyright (c) 2012 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/ui/panels/base_panel_browser_test.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/panels/detached_panel_collection.h"
#include "chrome/browser/ui/panels/native_panel.h"
#include "chrome/browser/ui/panels/panel_collection.h"
#include "chrome/browser/ui/panels/panel_mouse_watcher.h"
#include "chrome/browser/ui/panels/stacked_panel_collection.h"
#include "chrome/browser/ui/panels/test_panel_active_state_observer.h"
#include "chrome/browser/ui/panels/test_panel_mouse_watcher.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/notification_service.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/web_contents_tester.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/install_flag.h"
#include "extensions/common/manifest_constants.h"
#include "sync/api/string_ordinal.h"

#if defined(OS_LINUX)
#include "ui/base/x/x11_util.h"
#endif

#if defined(OS_MACOSX)
#include "base/mac/scoped_nsautorelease_pool.h"
#include "chrome/browser/ui/cocoa/run_loop_testing.h"
#endif

using content::WebContentsTester;
using extensions::Extension;

namespace {

const gfx::Rect kTestingPrimaryDisplayArea = gfx::Rect(0, 0, 800, 600);
const gfx::Rect kTestingPrimaryWorkArea = gfx::Rect(0, 0, 800, 580);

struct MockDesktopBar {
  bool auto_hiding_enabled;
  DisplaySettingsProvider::DesktopBarVisibility visibility;
  int thickness;
};

class MockDisplaySettingsProviderImpl :
    public BasePanelBrowserTest::MockDisplaySettingsProvider {
 public:
  explicit MockDisplaySettingsProviderImpl();
  virtual ~MockDisplaySettingsProviderImpl() { }

  // Overridden from DisplaySettingsProvider:
  virtual gfx::Rect GetPrimaryDisplayArea() const OVERRIDE;
  virtual gfx::Rect GetPrimaryWorkArea() const OVERRIDE;
  virtual gfx::Rect GetDisplayAreaMatching(
      const gfx::Rect& bounds) const OVERRIDE;
  virtual gfx::Rect GetWorkAreaMatching(
      const gfx::Rect& bounds) const OVERRIDE;
  virtual bool IsAutoHidingDesktopBarEnabled(
      DesktopBarAlignment alignment) OVERRIDE;
  virtual int GetDesktopBarThickness(
      DesktopBarAlignment alignment) const OVERRIDE;
  virtual DesktopBarVisibility GetDesktopBarVisibility(
      DesktopBarAlignment alignment) const OVERRIDE;
  virtual bool IsFullScreen() OVERRIDE;

  // Overridden from MockDisplaySettingsProvider:
  virtual void SetPrimaryDisplay(
      const gfx::Rect& display_area, const gfx::Rect& work_area) OVERRIDE;
  virtual void SetSecondaryDisplay(
      const gfx::Rect& display_area, const gfx::Rect& work_area) OVERRIDE;
  virtual void EnableAutoHidingDesktopBar(DesktopBarAlignment alignment,
                                          bool enabled,
                                          int thickness) OVERRIDE;
  virtual void SetDesktopBarVisibility(
      DesktopBarAlignment alignment, DesktopBarVisibility visibility) OVERRIDE;
  virtual void SetDesktopBarThickness(DesktopBarAlignment alignment,
                                      int thickness) OVERRIDE;
  virtual void EnableFullScreenMode(bool enabled) OVERRIDE;

 private:
  gfx::Rect primary_display_area_;
  gfx::Rect primary_work_area_;
  gfx::Rect secondary_display_area_;
  gfx::Rect secondary_work_area_;
  MockDesktopBar mock_desktop_bars[3];
  bool full_screen_enabled_;

  DISALLOW_COPY_AND_ASSIGN(MockDisplaySettingsProviderImpl);
};


MockDisplaySettingsProviderImpl::MockDisplaySettingsProviderImpl()
    : full_screen_enabled_(false) {
  memset(mock_desktop_bars, 0, sizeof(mock_desktop_bars));
}

gfx::Rect MockDisplaySettingsProviderImpl::GetPrimaryDisplayArea() const {
  return primary_display_area_;
}

gfx::Rect MockDisplaySettingsProviderImpl::GetPrimaryWorkArea() const {
  return primary_work_area_;
}

gfx::Rect MockDisplaySettingsProviderImpl::GetDisplayAreaMatching(
    const gfx::Rect& bounds) const {
  if (secondary_display_area_.IsEmpty())
    return primary_display_area_;

  gfx::Rect primary_intersection =
      gfx::IntersectRects(bounds, primary_display_area_);
  int primary_intersection_size =
      primary_intersection.width() * primary_intersection.height();

  gfx::Rect secondary_intersection =
      gfx::IntersectRects(bounds, secondary_display_area_);
  int secondary_intersection_size =
      secondary_intersection.width() * secondary_intersection.height();

  return primary_intersection_size >= secondary_intersection_size ?
      primary_display_area_ : secondary_display_area_;
}

gfx::Rect MockDisplaySettingsProviderImpl::GetWorkAreaMatching(
    const gfx::Rect& bounds) const {
  if (secondary_work_area_.IsEmpty())
    return primary_work_area_;

  gfx::Rect primary_intersection =
      gfx::IntersectRects(bounds, primary_work_area_);
  int primary_intersection_size =
      primary_intersection.width() * primary_intersection.height();

  gfx::Rect secondary_intersection =
      gfx::IntersectRects(bounds, secondary_work_area_);
  int secondary_intersection_size =
      secondary_intersection.width() * secondary_intersection.height();

  return primary_intersection_size >= secondary_intersection_size ?
      primary_work_area_ : secondary_work_area_;
}

bool MockDisplaySettingsProviderImpl::IsAutoHidingDesktopBarEnabled(
    DesktopBarAlignment alignment) {
  return mock_desktop_bars[static_cast<int>(alignment)].auto_hiding_enabled;
}

int MockDisplaySettingsProviderImpl::GetDesktopBarThickness(
    DesktopBarAlignment alignment) const {
  return mock_desktop_bars[static_cast<int>(alignment)].thickness;
}

DisplaySettingsProvider::DesktopBarVisibility
MockDisplaySettingsProviderImpl::GetDesktopBarVisibility(
    DesktopBarAlignment alignment) const {
  return mock_desktop_bars[static_cast<int>(alignment)].visibility;
}

bool MockDisplaySettingsProviderImpl::IsFullScreen() {
  return full_screen_enabled_;
}

void MockDisplaySettingsProviderImpl::EnableAutoHidingDesktopBar(
    DesktopBarAlignment alignment, bool enabled, int thickness) {
  MockDesktopBar* bar = &(mock_desktop_bars[static_cast<int>(alignment)]);
  bar->auto_hiding_enabled = enabled;
  bar->thickness = thickness;
}

void MockDisplaySettingsProviderImpl::SetPrimaryDisplay(
    const gfx::Rect& display_area, const gfx::Rect& work_area) {
  DCHECK(display_area.Contains(work_area));
  primary_display_area_ = display_area;
  primary_work_area_ = work_area;
  OnDisplaySettingsChanged();
}

void MockDisplaySettingsProviderImpl::SetSecondaryDisplay(
    const gfx::Rect& display_area, const gfx::Rect& work_area) {
  DCHECK(display_area.Contains(work_area));
  secondary_display_area_ = display_area;
  secondary_work_area_ = work_area;
  OnDisplaySettingsChanged();
}

void MockDisplaySettingsProviderImpl::SetDesktopBarVisibility(
    DesktopBarAlignment alignment, DesktopBarVisibility visibility) {
  MockDesktopBar* bar = &(mock_desktop_bars[static_cast<int>(alignment)]);
  if (!bar->auto_hiding_enabled)
    return;
  if (visibility == bar->visibility)
    return;
  bar->visibility = visibility;
  FOR_EACH_OBSERVER(
      DesktopBarObserver,
      desktop_bar_observers(),
      OnAutoHidingDesktopBarVisibilityChanged(alignment, visibility));
}

void MockDisplaySettingsProviderImpl::SetDesktopBarThickness(
    DesktopBarAlignment alignment, int thickness) {
  MockDesktopBar* bar = &(mock_desktop_bars[static_cast<int>(alignment)]);
  if (!bar->auto_hiding_enabled)
    return;
  if (thickness == bar->thickness)
    return;
  bar->thickness = thickness;
  FOR_EACH_OBSERVER(
      DesktopBarObserver,
      desktop_bar_observers(),
      OnAutoHidingDesktopBarThicknessChanged(alignment, thickness));
}

void MockDisplaySettingsProviderImpl::EnableFullScreenMode(bool enabled) {
  full_screen_enabled_ = enabled;
  CheckFullScreenMode(PERFORM_FULLSCREEN_CHECK);
}

}  // namespace

const base::FilePath::CharType* BasePanelBrowserTest::kTestDir =
    FILE_PATH_LITERAL("panels");

BasePanelBrowserTest::BasePanelBrowserTest()
    : InProcessBrowserTest(),
      mock_display_settings_enabled_(true) {
}

BasePanelBrowserTest::~BasePanelBrowserTest() {
}

bool BasePanelBrowserTest::SkipTestIfIceWM() {
#if defined(OS_LINUX) && defined(USE_X11)
  return ui::GuessWindowManager() == ui::WM_ICE_WM;
#else
  return false;
#endif
}

bool BasePanelBrowserTest::SkipTestIfCompizWM() {
#if defined(OS_LINUX) && defined(USE_X11)
  return ui::GuessWindowManager() == ui::WM_COMPIZ;
#else
  return false;
#endif
}

void BasePanelBrowserTest::SetUpCommandLine(CommandLine* command_line) {
  command_line->AppendSwitch(switches::kEnablePanels);
}

void BasePanelBrowserTest::SetUpOnMainThread() {
  InProcessBrowserTest::SetUpOnMainThread();

  // Setup the work area and desktop bar so that we have consistent testing
  // environment for all panel related tests.
  if (mock_display_settings_enabled_) {
    mock_display_settings_provider_ = new MockDisplaySettingsProviderImpl();
    mock_display_settings_provider_->SetPrimaryDisplay(
        kTestingPrimaryDisplayArea, kTestingPrimaryWorkArea);
    PanelManager::SetDisplaySettingsProviderForTesting(
        mock_display_settings_provider_);
  }

  PanelManager* panel_manager = PanelManager::GetInstance();
  panel_manager->enable_auto_sizing(false);

  PanelManager::shorten_time_intervals_for_testing();

  // Simulate the mouse movement so that tests are not affected by actual mouse
  // events.
  PanelMouseWatcher* mouse_watcher = new TestPanelMouseWatcher();
  panel_manager->SetMouseWatcherForTesting(mouse_watcher);

  // This is needed so the subsequently created panels can be activated.
  // On a Mac, it transforms background-only test process into foreground one.
  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
}

void BasePanelBrowserTest::WaitForPanelActiveState(
    Panel* panel, ActiveState expected_state) {
  DCHECK(expected_state == SHOW_AS_ACTIVE ||
         expected_state == SHOW_AS_INACTIVE);

#if defined(OS_MACOSX)
  scoped_ptr<NativePanelTesting> panel_testing(
      CreateNativePanelTesting(panel));
  ASSERT_TRUE(panel_testing->EnsureApplicationRunOnForeground()) <<
      "Failed to bring application to foreground. Bail out.";
#endif

  PanelActiveStateObserver signal(panel, expected_state == SHOW_AS_ACTIVE);
  signal.Wait();
}

void BasePanelBrowserTest::WaitForWindowSizeAvailable(Panel* panel) {
  scoped_ptr<NativePanelTesting> panel_testing(
      CreateNativePanelTesting(panel));
  content::WindowedNotificationObserver signal(
      chrome::NOTIFICATION_PANEL_WINDOW_SIZE_KNOWN,
      content::Source<Panel>(panel));
  if (panel_testing->IsWindowSizeKnown())
    return;
  signal.Wait();
  EXPECT_TRUE(panel_testing->IsWindowSizeKnown());
}

void BasePanelBrowserTest::WaitForBoundsAnimationFinished(Panel* panel) {
  scoped_ptr<NativePanelTesting> panel_testing(
      CreateNativePanelTesting(panel));
  // Sometimes there are several animations in sequence due to content
  // auto resizing. Wait for all animations to finish.
  while (panel_testing->IsAnimatingBounds()) {
    content::WindowedNotificationObserver signal(
        chrome::NOTIFICATION_PANEL_BOUNDS_ANIMATIONS_FINISHED,
        content::Source<Panel>(panel));
    if (!panel_testing->IsAnimatingBounds())
      return;
    signal.Wait();
  }
}

BasePanelBrowserTest::CreatePanelParams::CreatePanelParams(
    const std::string& name,
    const gfx::Rect& bounds,
    ActiveState show_flag)
    : name(name),
      bounds(bounds),
      show_flag(show_flag),
      wait_for_fully_created(true),
      expected_active_state(show_flag),
      create_mode(PanelManager::CREATE_AS_DOCKED),
      profile(NULL) {
}

Panel* BasePanelBrowserTest::CreatePanelWithParams(
    const CreatePanelParams& params) {
#if defined(OS_MACOSX)
  // Opening panels on a Mac causes NSWindowController of the Panel window
  // to be autoreleased. We need a pool drained after it's done so the test
  // can close correctly. The NSWindowController of the Panel window controls
  // lifetime of the Panel object so we want to release it as soon as
  // possible. In real Chrome, this is done by message pump.
  // On non-Mac platform, this is an empty class.
  base::mac::ScopedNSAutoreleasePool autorelease_pool;
#endif

  content::WindowedNotificationObserver observer(
      content::NOTIFICATION_LOAD_STOP,
      content::NotificationService::AllSources());

  PanelManager* manager = PanelManager::GetInstance();
  Panel* panel = manager->CreatePanel(
      params.name,
      params.profile ? params.profile : browser()->profile(),
      params.url,
      params.bounds,
      params.create_mode);

  if (!params.url.is_empty())
    observer.Wait();

  if (!manager->auto_sizing_enabled() ||
      params.bounds.width() || params.bounds.height()) {
    EXPECT_FALSE(panel->auto_resizable());
  } else {
    EXPECT_TRUE(panel->auto_resizable());
  }

  if (params.show_flag == SHOW_AS_ACTIVE) {
    panel->Show();
  } else {
    panel->ShowInactive();
  }

  if (params.wait_for_fully_created) {
    base::MessageLoopForUI::current()->RunUntilIdle();

#if defined(OS_LINUX) && defined(USE_X11)
    // On bots, we might have a simple window manager which always activates new
    // windows, and can't always deactivate them. Re-activate the main tabbed
    // browser to "deactivate" the newly created panel.
    if (params.expected_active_state == SHOW_AS_INACTIVE &&
        ui::GuessWindowManager() == ui::WM_ICE_WM) {
      // Wait for new panel to become active before deactivating to ensure
      // the activated notification is consumed before we wait for the panel
      // to become inactive.
      WaitForPanelActiveState(panel, SHOW_AS_ACTIVE);
      browser()->window()->Activate();
    }
#endif
    // More waiting, because gaining or losing focus may require inter-process
    // asynchronous communication, and it is not enough to just run the local
    // message loop to make sure this activity has completed.
    WaitForPanelActiveState(panel, params.expected_active_state);

    // On Linux, window size is not available right away and we should wait
    // before moving forward with the test.
    WaitForWindowSizeAvailable(panel);

    // Wait for the bounds animations on creation to finish.
    WaitForBoundsAnimationFinished(panel);
  }

  return panel;
}

Panel* BasePanelBrowserTest::CreatePanelWithBounds(
    const std::string& panel_name, const gfx::Rect& bounds) {
  CreatePanelParams params(panel_name, bounds, SHOW_AS_ACTIVE);
  return CreatePanelWithParams(params);
}

Panel* BasePanelBrowserTest::CreatePanel(const std::string& panel_name) {
  CreatePanelParams params(panel_name, gfx::Rect(), SHOW_AS_ACTIVE);
  return CreatePanelWithParams(params);
}

Panel* BasePanelBrowserTest::CreateDockedPanel(const std::string& name,
                                               const gfx::Rect& bounds) {
  Panel* panel = CreatePanelWithBounds(name, bounds);
  EXPECT_EQ(PanelCollection::DOCKED, panel->collection()->type());
  return panel;
}

Panel* BasePanelBrowserTest::CreateDetachedPanel(const std::string& name,
                                                 const gfx::Rect& bounds) {
  Panel* panel = CreatePanelWithBounds(name, bounds);
  PanelManager* panel_manager = panel->manager();
  panel_manager->MovePanelToCollection(panel,
                                       panel_manager->detached_collection(),
                                       PanelCollection::DEFAULT_POSITION);
  EXPECT_EQ(PanelCollection::DETACHED, panel->collection()->type());
  // The panel is first created as docked panel, which ignores the specified
  // origin in |bounds|. We need to reposition the panel after it becomes
  // detached.
  panel->SetPanelBounds(bounds);
  WaitForBoundsAnimationFinished(panel);
  return panel;
}

Panel* BasePanelBrowserTest::CreateStackedPanel(const std::string& name,
                                                const gfx::Rect& bounds,
                                                StackedPanelCollection* stack) {
  Panel* panel = CreateDetachedPanel(name, bounds);
  panel->manager()->MovePanelToCollection(
      panel,
      stack,
      static_cast<PanelCollection::PositioningMask>(
          PanelCollection::DEFAULT_POSITION |
          PanelCollection::COLLAPSE_TO_FIT));
  EXPECT_EQ(PanelCollection::STACKED, panel->collection()->type());
  WaitForBoundsAnimationFinished(panel);
  return panel;
}

Panel* BasePanelBrowserTest::CreateInactivePanel(const std::string& name) {
  // Create an active panel first, instead of inactive panel. This is because
  // certain window managers on Linux, like icewm, will always activate the
  // new window.
  Panel* panel = CreatePanel(name);

  DeactivatePanel(panel);
  WaitForPanelActiveState(panel, SHOW_AS_INACTIVE);

  return panel;
}

Panel* BasePanelBrowserTest::CreateInactiveDockedPanel(
    const std::string& name, const gfx::Rect& bounds) {
  // Create an active panel first, instead of inactive panel. This is because
  // certain window managers on Linux, like icewm, will always activate the
  // new window.
  Panel* panel = CreateDockedPanel(name, bounds);

  DeactivatePanel(panel);
  WaitForPanelActiveState(panel, SHOW_AS_INACTIVE);

  return panel;
}

Panel* BasePanelBrowserTest::CreateInactiveDetachedPanel(
    const std::string& name, const gfx::Rect& bounds) {
  // Create an active panel first, instead of inactive panel. This is because
  // certain window managers on Linux, like icewm, will always activate the
  // new window.
  Panel* panel = CreateDetachedPanel(name, bounds);

  DeactivatePanel(panel);
  WaitForPanelActiveState(panel, SHOW_AS_INACTIVE);

  return panel;
}

void BasePanelBrowserTest::ActivatePanel(Panel* panel) {
  // For certain window managers on Linux, the window activation/deactivation
  // signals might not be sent. To work around this, we explicitly deactivate
  // all other panels first.
#if defined(OS_LINUX)
  std::vector<Panel*> panels = PanelManager::GetInstance()->panels();
  for (std::vector<Panel*>::const_iterator iter = panels.begin();
       iter != panels.end(); ++iter) {
    Panel* current_panel = *iter;
    if (panel != current_panel)
      current_panel->Deactivate();
  }
#endif

  panel->Activate();
}

void BasePanelBrowserTest::DeactivatePanel(Panel* panel) {
#if defined(OS_LINUX)
  // For certain window managers on Linux, like icewm, panel activation and
  // deactivation notification might not get tiggered when non-panel window is
  // activated or deactivated. So we deactivate the panel directly.
  panel->Deactivate();
#else
  // Make the panel lose focus by activating the browser window. This is
  // because:
  // 1) On Windows, deactivating the panel window might cause the application
  //    to lose the foreground status. When this occurs, trying to activate
  //    the panel window again will not be allowed by the system.
  // 2) On MacOS, deactivating a window is not supported by Cocoa.
  browser()->window()->Activate();
#endif
}

// static
NativePanelTesting* BasePanelBrowserTest::CreateNativePanelTesting(
    Panel* panel) {
  return panel->native_panel()->CreateNativePanelTesting();
}

scoped_refptr<Extension> BasePanelBrowserTest::CreateExtension(
    const base::FilePath::StringType& path,
    extensions::Manifest::Location location,
    const base::DictionaryValue& extra_value) {
  extensions::ExtensionPrefs* extension_prefs =
      extensions::ExtensionPrefs::Get(browser()->profile());
  base::FilePath full_path = extension_prefs->install_directory().Append(path);

  scoped_ptr<base::DictionaryValue> input_value(extra_value.DeepCopy());
  input_value->SetString(extensions::manifest_keys::kVersion, "1.0.0.0");
  input_value->SetString(extensions::manifest_keys::kName, "Sample Extension");

  std::string error;
  scoped_refptr<Extension> extension = Extension::Create(
      full_path,  location, *input_value, Extension::NO_FLAGS, &error);
  EXPECT_TRUE(extension.get());
  EXPECT_STREQ("", error.c_str());
  extensions::ExtensionSystem::Get(
      browser()->profile())->extension_service()->OnExtensionInstalled(
          extension.get(),
          syncer::StringOrdinal(),
          extensions::kInstallFlagInstallImmediately);
  return extension;
}

void BasePanelBrowserTest::CloseWindowAndWait(Panel* panel) {
  // Closing a panel may involve several async tasks. Need to use
  // message pump and wait for the notification.
  PanelManager* manager = PanelManager::GetInstance();
  int panel_count = manager->num_panels();
  content::WindowedNotificationObserver signal(
      chrome::NOTIFICATION_PANEL_CLOSED,
      content::Source<Panel>(panel));
  panel->Close();
  signal.Wait();
  // Now we have one less panel.
  EXPECT_EQ(panel_count - 1, manager->num_panels());

#if defined(OS_MACOSX)
  // Mac window controllers may be autoreleased, and in the non-test
  // environment, may actually depend on the autorelease pool being recycled
  // with the run loop in order to perform important work. Replicate this in
  // the test environment.
  AutoreleasePool()->Recycle();

  // Make sure that everything has a chance to run.
  chrome::testing::NSRunLoopRunAllPending();
#endif  // OS_MACOSX
}

void BasePanelBrowserTest::MoveMouseAndWaitForExpansionStateChange(
    Panel* panel,
    const gfx::Point& position) {
  content::WindowedNotificationObserver signal(
      chrome::NOTIFICATION_PANEL_CHANGED_EXPANSION_STATE,
      content::Source<Panel>(panel));
  MoveMouse(position);
  signal.Wait();
}

void BasePanelBrowserTest::MoveMouse(const gfx::Point& position) {
  PanelManager::GetInstance()->mouse_watcher()->NotifyMouseMovement(position);
}

std::string BasePanelBrowserTest::MakePanelName(int index) {
  std::string panel_name("Panel");
  return panel_name + base::IntToString(index);
}

bool BasePanelBrowserTest::WmSupportWindowActivation() {
  return true;
}
