#include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/extensions/extension_test_message_listener.h"
+#include "chrome/browser/sessions/session_tab_helper.h"
+#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.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/browser/web_contents.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_system.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/extension_set.h"
#include "extensions/common/permissions/permissions_data.h"
+#include "extensions/test/extension_test_message_listener.h"
+#include "extensions/test/result_catcher.h"
+
+#if defined(OS_WIN)
+#include "ui/views/win/hwnd_util.h"
+#endif
namespace extensions {
namespace {
return true;
#endif
}
+
+ // Open an extension popup via the chrome.browserAction.openPopup API.
+ void OpenExtensionPopupViaAPI() {
+ // Setup the notification observer to wait for the popup to finish loading.
+ content::WindowedNotificationObserver frame_observer(
+ content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
+ content::NotificationService::AllSources());
+ // Show first popup in first window and expect it to have loaded.
+ ASSERT_TRUE(RunExtensionSubtest("browser_action/open_popup",
+ "open_popup_succeeds.html")) << message_;
+ frame_observer.Wait();
+ EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
+ }
};
// Tests opening a popup using the chrome.browserAction.openPopup API. This test
// Setup extension message listener to wait for javascript to finish running.
ExtensionTestMessageListener listener("ready", true);
{
- // Setup the notification observer to wait for the popup to finish loading.
- content::WindowedNotificationObserver frame_observer(
- content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
- content::NotificationService::AllSources());
- // Show first popup in first window and expect it to have loaded.
- ASSERT_TRUE(RunExtensionSubtest("browser_action/open_popup",
- "open_popup_succeeds.html")) << message_;
- frame_observer.Wait();
+ OpenExtensionPopupViaAPI();
EXPECT_TRUE(browserActionBar.HasPopup());
browserActionBar.HidePopup();
}
new_browser = chrome::FindBrowserWithWebContents(
browser()->OpenURL(content::OpenURLParams(
GURL("about:"), content::Referrer(), NEW_WINDOW,
- content::PAGE_TRANSITION_TYPED, false)));
+ ui::PAGE_TRANSITION_TYPED, false)));
#if defined(OS_WIN)
// Hide all the buttons to test that it opens even when browser action is
// in the overflow bucket.
if (!ShouldRunPopupTest())
return;
- content::WindowedNotificationObserver frame_observer(
- content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
- content::NotificationService::AllSources());
- ASSERT_TRUE(RunExtensionSubtest("browser_action/open_popup",
- "open_popup_succeeds.html")) << message_;
- frame_observer.Wait();
-
+ OpenExtensionPopupViaAPI();
ExtensionService* service = extensions::ExtensionSystem::Get(
browser()->profile())->extension_service();
- ASSERT_FALSE(PermissionsData::HasAPIPermissionForTab(
- service->GetExtensionById(last_loaded_extension_id(), false),
- SessionID::IdForTab(browser()->tab_strip_model()->GetActiveWebContents()),
- APIPermission::kTab));
+ ASSERT_FALSE(
+ service->GetExtensionById(last_loaded_extension_id(), false)
+ ->permissions_data()
+ ->HasAPIPermissionForTab(
+ SessionTabHelper::IdForTab(
+ browser()->tab_strip_model()->GetActiveWebContents()),
+ APIPermission::kTab));
}
// Test that the extension popup is closed when the browser window is clicked.
if (!ShouldRunPopupTest())
return;
- // Add a second tab to the browser.
+ // Add a second tab to the browser and open an extension popup.
chrome::NewTab(browser());
ASSERT_EQ(2, browser()->tab_strip_model()->count());
+ OpenExtensionPopupViaAPI();
- // Open an extension popup via the chrome.browserAction.openPopup API.
+ // Press CTRL+TAB to change active tabs, the extension popup should close.
+ ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
+ browser(), ui::VKEY_TAB, true, false, false, false));
+ EXPECT_FALSE(BrowserActionTestUtil(browser()).HasPopup());
+}
+
+IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
+ DeleteBrowserActionWithPopupOpen) {
+ if (!ShouldRunPopupTest())
+ return;
+
+ // First, we open a popup.
+ OpenExtensionPopupViaAPI();
+ BrowserActionTestUtil browser_action_test_util(browser());
+ EXPECT_TRUE(browser_action_test_util.HasPopup());
+
+ // Then, find the extension that created it.
+ content::WebContents* active_web_contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ ASSERT_TRUE(active_web_contents);
+ GURL url = active_web_contents->GetLastCommittedURL();
+ const Extension* extension = ExtensionRegistry::Get(browser()->profile())->
+ enabled_extensions().GetExtensionOrAppByURL(url);
+ ASSERT_TRUE(extension);
+
+ // Finally, uninstall the extension, which causes the view to be deleted and
+ // the popup to go away. This should not crash.
+ UninstallExtension(extension->id());
+ EXPECT_FALSE(browser_action_test_util.HasPopup());
+}
+
+#if defined(TOOLKIT_VIEWS)
+// Test closing the browser while inspecting an extension popup with dev tools.
+IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, CloseBrowserWithDevTools) {
+ if (!ShouldRunPopupTest())
+ return;
+
+ // Load a first extension that can open a popup.
+ ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
+ "browser_action/popup")));
+ const Extension* extension = GetSingleLoadedExtension();
+ ASSERT_TRUE(extension) << message_;
+
+ // Open an extension popup by clicking the browser action button.
content::WindowedNotificationObserver frame_observer(
content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
content::NotificationService::AllSources());
- ASSERT_TRUE(RunExtensionSubtest("browser_action/open_popup",
- "open_popup_succeeds.html")) << message_;
+ BrowserActionTestUtil(browser()).InspectPopup(0);
frame_observer.Wait();
EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
- // Press CTRL+TAB to change active tabs, the extension popup should close.
- ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
- browser(), ui::VKEY_TAB, true, false, false, false));
- EXPECT_FALSE(BrowserActionTestUtil(browser()).HasPopup());
+ // Close the browser window, this should not cause a crash.
+ chrome::CloseWindow(browser());
+}
+#endif // TOOLKIT_VIEWS
+
+#if defined(OS_WIN)
+// Test that forcibly closing the browser and popup HWND does not cause a crash.
+// http://crbug.com/400646
+IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
+ DISABLED_DestroyHWNDDoesNotCrash) {
+ if (!ShouldRunPopupTest())
+ return;
+
+ OpenExtensionPopupViaAPI();
+ BrowserActionTestUtil test_util(browser());
+ const gfx::NativeView view = test_util.GetPopupNativeView();
+ EXPECT_NE(static_cast<gfx::NativeView>(NULL), view);
+ const HWND hwnd = views::HWNDForNativeView(view);
+ EXPECT_EQ(hwnd,
+ views::HWNDForNativeView(browser()->window()->GetNativeWindow()));
+ EXPECT_EQ(TRUE, ::IsWindow(hwnd));
+
+ // Create a new browser window to prevent the message loop from terminating.
+ Browser* new_browser = chrome::FindBrowserWithWebContents(
+ browser()->OpenURL(content::OpenURLParams(
+ GURL("about:"), content::Referrer(), NEW_WINDOW,
+ ui::PAGE_TRANSITION_TYPED, false)));
+
+ // Forcibly closing the browser HWND should not cause a crash.
+ EXPECT_EQ(TRUE, ::CloseWindow(hwnd));
+ EXPECT_EQ(TRUE, ::DestroyWindow(hwnd));
+ EXPECT_EQ(FALSE, ::IsWindow(hwnd));
}
+#endif // OS_WIN
} // namespace
} // namespace extensions