root/components/web_modal/web_contents_modal_dialog_manager_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ManageDialog
  2. ShowDialog
  3. HideDialog
  4. CloseDialog
  5. FocusDialog
  6. PulseDialog
  7. HostChanged
  8. GetCloseCount
  9. GetDialogState
  10. native_manager
  11. SetUp
  12. TearDown
  13. MakeFakeDialog
  14. CreateNativeManager
  15. TEST_F
  16. TEST_F
  17. TEST_F
  18. TEST_F
  19. TEST_F
  20. TEST_F
  21. TEST_F

// 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 "components/web_modal/web_contents_modal_dialog_manager.h"

#include <map>

#include "base/memory/scoped_ptr.h"
#include "components/web_modal/native_web_contents_modal_dialog_manager.h"
#include "components/web_modal/test_web_contents_modal_dialog_manager_delegate.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace web_modal {

class TestNativeWebContentsModalDialogManager
    : public NativeWebContentsModalDialogManager {
 public:
  enum DialogState {
    UNKNOWN,
    NOT_SHOWN,
    SHOWN,
    HIDDEN,
    CLOSED
  };

  explicit TestNativeWebContentsModalDialogManager(
      NativeWebContentsModalDialogManagerDelegate* delegate)
      : delegate_(delegate) {}
  virtual void ManageDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
    dialog_state_[dialog] = NOT_SHOWN;
  }
  virtual void ShowDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
    dialog_state_[dialog] = SHOWN;
  }
  virtual void HideDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
    dialog_state_[dialog] = HIDDEN;
  }
  virtual void CloseDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
    delegate_->WillClose(dialog);
    dialog_state_[dialog] = CLOSED;
  }
  virtual void FocusDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
  }
  virtual void PulseDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
  }
  virtual void HostChanged(WebContentsModalDialogHost* new_host) OVERRIDE {
  }

  int GetCloseCount() const {
    int count = 0;
    for (DialogStateMap::const_iterator it = dialog_state_.begin();
         it != dialog_state_.end(); ++it) {
      if (it->second == CLOSED)
        count++;
    }
    return count;
  }

  DialogState GetDialogState(NativeWebContentsModalDialog dialog) const {
    DialogStateMap::const_iterator loc = dialog_state_.find(dialog);
    return loc == dialog_state_.end() ? UNKNOWN : loc->second;
  }

 private:
  typedef std::map<NativeWebContentsModalDialog, DialogState> DialogStateMap;

  NativeWebContentsModalDialogManagerDelegate* delegate_;
  DialogStateMap dialog_state_;

  DISALLOW_COPY_AND_ASSIGN(TestNativeWebContentsModalDialogManager);
};

class WebContentsModalDialogManagerTest
    : public content::RenderViewHostTestHarness {
 public:
  WebContentsModalDialogManagerTest()
      : next_dialog_id(1),
        manager(NULL),
        native_manager(NULL) {
  }

  virtual void SetUp() {
    content::RenderViewHostTestHarness::SetUp();

    delegate.reset(new TestWebContentsModalDialogManagerDelegate);
    WebContentsModalDialogManager::CreateForWebContents(web_contents());
    manager = WebContentsModalDialogManager::FromWebContents(web_contents());
    manager->SetDelegate(delegate.get());
    test_api.reset(new WebContentsModalDialogManager::TestApi(manager));
    native_manager = new TestNativeWebContentsModalDialogManager(manager);

    // |manager| owns |native_manager| as a result.
    test_api->ResetNativeManager(native_manager);
  }

  virtual void TearDown() {
    test_api.reset();
    content::RenderViewHostTestHarness::TearDown();
  }

 protected:
  NativeWebContentsModalDialog MakeFakeDialog() {
    // WebContentsModalDialogManager treats the NativeWebContentsModalDialog as
    // an opaque type, so creating fake NativeWebContentsModalDialogs using
    // reinterpret_cast is valid.
    return reinterpret_cast<NativeWebContentsModalDialog>(next_dialog_id++);
  }

  int next_dialog_id;
  scoped_ptr<TestWebContentsModalDialogManagerDelegate> delegate;
  WebContentsModalDialogManager* manager;
  scoped_ptr<WebContentsModalDialogManager::TestApi> test_api;
  TestNativeWebContentsModalDialogManager* native_manager;

  DISALLOW_COPY_AND_ASSIGN(WebContentsModalDialogManagerTest);
};

NativeWebContentsModalDialogManager*
WebContentsModalDialogManager::CreateNativeManager(
    NativeWebContentsModalDialogManagerDelegate* native_delegate) {
  return new TestNativeWebContentsModalDialogManager(native_delegate);
}

// Test that the dialog is shown immediately when the delegate indicates the web
// contents is visible.
TEST_F(WebContentsModalDialogManagerTest, WebContentsVisible) {
  // Dialog should be shown while WebContents is visible.
  const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();

  manager->ShowDialog(dialog1);

  EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
            native_manager->GetDialogState(dialog1));
  EXPECT_TRUE(manager->IsDialogActive());
  EXPECT_TRUE(delegate->web_contents_blocked());
}

// Test that the dialog is not shown immediately when the delegate indicates the
// web contents is not visible.
TEST_F(WebContentsModalDialogManagerTest, WebContentsNotVisible) {
  // Dialog should not be shown while WebContents is not visible.
  delegate->set_web_contents_visible(false);

  const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();

  manager->ShowDialog(dialog1);

  EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN,
            native_manager->GetDialogState(dialog1));
  EXPECT_TRUE(manager->IsDialogActive());
  EXPECT_TRUE(delegate->web_contents_blocked());
}

// Test that only the first of multiple dialogs is shown.
TEST_F(WebContentsModalDialogManagerTest, ShowDialogs) {
  const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();
  const NativeWebContentsModalDialog dialog2 = MakeFakeDialog();
  const NativeWebContentsModalDialog dialog3 = MakeFakeDialog();

  manager->ShowDialog(dialog1);
  manager->ShowDialog(dialog2);
  manager->ShowDialog(dialog3);

  EXPECT_TRUE(delegate->web_contents_blocked());
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
            native_manager->GetDialogState(dialog1));
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN,
            native_manager->GetDialogState(dialog2));
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN,
            native_manager->GetDialogState(dialog3));
}

// Test that the dialog is shown/hidden when the WebContents is shown/hidden.
TEST_F(WebContentsModalDialogManagerTest, VisibilityObservation) {
  const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();

  manager->ShowDialog(dialog1);

  EXPECT_TRUE(manager->IsDialogActive());
  EXPECT_TRUE(delegate->web_contents_blocked());
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
            native_manager->GetDialogState(dialog1));

  test_api->WebContentsWasHidden();

  EXPECT_TRUE(manager->IsDialogActive());
  EXPECT_TRUE(delegate->web_contents_blocked());
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::HIDDEN,
            native_manager->GetDialogState(dialog1));

  test_api->WebContentsWasShown();

  EXPECT_TRUE(manager->IsDialogActive());
  EXPECT_TRUE(delegate->web_contents_blocked());
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
            native_manager->GetDialogState(dialog1));
}

// Test that attaching an interstitial page closes dialogs configured to close.
TEST_F(WebContentsModalDialogManagerTest, InterstitialPage) {
  const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();
  const NativeWebContentsModalDialog dialog2 = MakeFakeDialog();
  const NativeWebContentsModalDialog dialog3 = MakeFakeDialog();

  manager->ShowDialog(dialog1);
  manager->ShowDialog(dialog2);
  manager->ShowDialog(dialog3);

#if defined(OS_WIN) || defined(USE_AURA)
  manager->SetCloseOnInterstitialPage(dialog2, false);
#else
  // TODO(wittman): Remove this section once Mac is changed to close on
  // interstitial pages by default.
  manager->SetCloseOnInterstitialPage(dialog1, true);
  manager->SetCloseOnInterstitialPage(dialog3, true);
#endif

  test_api->DidAttachInterstitialPage();
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED,
            native_manager->GetDialogState(dialog1));
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
            native_manager->GetDialogState(dialog2));
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED,
            native_manager->GetDialogState(dialog3));
}


// Test that the first dialog is always shown, regardless of the order in which
// dialogs are closed.
TEST_F(WebContentsModalDialogManagerTest, CloseDialogs) {
  // The front dialog is always shown regardless of dialog close order.
  const NativeWebContentsModalDialog dialog1 = MakeFakeDialog();
  const NativeWebContentsModalDialog dialog2 = MakeFakeDialog();
  const NativeWebContentsModalDialog dialog3 = MakeFakeDialog();
  const NativeWebContentsModalDialog dialog4 = MakeFakeDialog();

  manager->ShowDialog(dialog1);
  manager->ShowDialog(dialog2);
  manager->ShowDialog(dialog3);
  manager->ShowDialog(dialog4);

  native_manager->CloseDialog(dialog1);

  EXPECT_TRUE(manager->IsDialogActive());
  EXPECT_TRUE(delegate->web_contents_blocked());
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED,
            native_manager->GetDialogState(dialog1));
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
            native_manager->GetDialogState(dialog2));
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN,
            native_manager->GetDialogState(dialog3));
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN,
            native_manager->GetDialogState(dialog4));

  native_manager->CloseDialog(dialog3);

  EXPECT_TRUE(manager->IsDialogActive());
  EXPECT_TRUE(delegate->web_contents_blocked());
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
            native_manager->GetDialogState(dialog2));
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED,
            native_manager->GetDialogState(dialog3));
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::NOT_SHOWN,
            native_manager->GetDialogState(dialog4));

  native_manager->CloseDialog(dialog2);

  EXPECT_TRUE(manager->IsDialogActive());
  EXPECT_TRUE(delegate->web_contents_blocked());
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED,
            native_manager->GetDialogState(dialog2));
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::SHOWN,
            native_manager->GetDialogState(dialog4));

  native_manager->CloseDialog(dialog4);

  EXPECT_FALSE(manager->IsDialogActive());
  EXPECT_FALSE(delegate->web_contents_blocked());
  EXPECT_EQ(TestNativeWebContentsModalDialogManager::CLOSED,
            native_manager->GetDialogState(dialog4));
}

// Test that CloseAllDialogs does what it says.
TEST_F(WebContentsModalDialogManagerTest, CloseAllDialogs) {
  const int kWindowCount = 4;
  for (int i = 0; i < kWindowCount; i++)
    manager->ShowDialog(MakeFakeDialog());

  EXPECT_EQ(0, native_manager->GetCloseCount());

  test_api->CloseAllDialogs();
  EXPECT_FALSE(delegate->web_contents_blocked());
  EXPECT_FALSE(manager->IsDialogActive());
  EXPECT_EQ(kWindowCount, native_manager->GetCloseCount());
}

}  // namespace web_modal

/* [<][>][^][v][top][bottom][index][help] */