1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/command_line.h" 6 #include "base/file_path.h" 7 #include "base/utf_string_conversions.h" 8 #include "chrome/browser/extensions/extension_browsertest.h" 9 #include "chrome/browser/extensions/extension_service.h" 10 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/ui/browser.h" 12 #include "chrome/browser/ui/browser_init.h" 13 #include "chrome/browser/ui/browser_list.h" 14 #include "chrome/browser/ui/browser_window.h" 15 #include "chrome/common/chrome_switches.h" 16 #include "chrome/test/in_process_browser_test.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 19 class BrowserInitTest : public ExtensionBrowserTest { 20 protected: 21 // Helper functions return void so that we can ASSERT*(). 22 // Use ASSERT_FALSE(HasFatalFailure()) after calling these functions 23 // to stop the test if an assert fails. 24 void LoadApp(const std::string& app_name, 25 const Extension** out_app_extension) { 26 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(app_name.c_str()))); 27 28 ExtensionService* service = browser()->profile()->GetExtensionService(); 29 *out_app_extension = service->GetExtensionById( 30 last_loaded_extension_id_, false); 31 ASSERT_TRUE(*out_app_extension); 32 33 // Code that opens a new browser assumes we start with exactly one. 34 ASSERT_EQ(1u, BrowserList::GetBrowserCount(browser()->profile())); 35 } 36 37 void SetAppLaunchPref(const std::string& app_id, 38 ExtensionPrefs::LaunchType launch_type) { 39 ExtensionService* service = browser()->profile()->GetExtensionService(); 40 service->extension_prefs()->SetLaunchType(app_id, launch_type); 41 } 42 43 // Check that there are two browsers. Find the one that is not |browser()|. 44 void FindOneOtherBrowser(Browser** out_other_browser) { 45 // There should only be one other browser. 46 ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile())); 47 48 // Find the new browser. 49 Browser* other_browser = NULL; 50 for (BrowserList::const_iterator i = BrowserList::begin(); 51 i != BrowserList::end() && !other_browser; ++i) { 52 if (*i != browser()) 53 other_browser = *i; 54 } 55 ASSERT_TRUE(other_browser); 56 ASSERT_TRUE(other_browser != browser()); 57 *out_other_browser = other_browser; 58 } 59 }; 60 61 class OpenURLsPopupObserver : public BrowserList::Observer { 62 public: 63 OpenURLsPopupObserver() : added_browser_(NULL) { } 64 65 virtual void OnBrowserAdded(const Browser* browser) { 66 added_browser_ = browser; 67 } 68 69 virtual void OnBrowserRemoved(const Browser* browser) { } 70 71 const Browser* added_browser_; 72 }; 73 74 // Test that when there is a popup as the active browser any requests to 75 // BrowserInit::LaunchWithProfile::OpenURLsInBrowser don't crash because 76 // there's no explicit profile given. 77 IN_PROC_BROWSER_TEST_F(BrowserInitTest, OpenURLsPopup) { 78 std::vector<GURL> urls; 79 urls.push_back(GURL("http://localhost")); 80 81 // Note that in our testing we do not ever query the BrowserList for the "last 82 // active" browser. That's because the browsers are set as "active" by 83 // platform UI toolkit messages, and those messages are not sent during unit 84 // testing sessions. 85 86 OpenURLsPopupObserver observer; 87 BrowserList::AddObserver(&observer); 88 89 Browser* popup = Browser::CreateForType(Browser::TYPE_POPUP, 90 browser()->profile()); 91 ASSERT_EQ(popup->type(), Browser::TYPE_POPUP); 92 ASSERT_EQ(popup, observer.added_browser_); 93 94 CommandLine dummy(CommandLine::NO_PROGRAM); 95 BrowserInit::LaunchWithProfile launch(FilePath(), dummy); 96 // This should create a new window, but re-use the profile from |popup|. If 97 // it used a NULL or invalid profile, it would crash. 98 launch.OpenURLsInBrowser(popup, false, urls); 99 ASSERT_NE(popup, observer.added_browser_); 100 BrowserList::RemoveObserver(&observer); 101 } 102 103 // App shortcuts are not implemented on mac os. 104 #if !defined(OS_MACOSX) 105 IN_PROC_BROWSER_TEST_F(BrowserInitTest, OpenAppShortcutNoPref) { 106 // Load an app with launch.container = 'tab'. 107 const Extension* extension_app = NULL; 108 LoadApp("app_with_tab_container", &extension_app); 109 ASSERT_FALSE(HasFatalFailure()); // Check for ASSERT failures in LoadApp(). 110 111 // Add --app-id=<extension->id()> to the command line. 112 CommandLine command_line(CommandLine::NO_PROGRAM); 113 command_line.AppendSwitchASCII(switches::kAppId, extension_app->id()); 114 115 BrowserInit::LaunchWithProfile launch(FilePath(), command_line); 116 ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), false)); 117 118 // No pref was set, so the app should have opened in a window. 119 // The launch should have created a new browser. 120 Browser* new_browser = NULL; 121 FindOneOtherBrowser(&new_browser); 122 ASSERT_FALSE(HasFatalFailure()); 123 124 // Expect an app window. 125 EXPECT_EQ(Browser::TYPE_APP, new_browser->type()); 126 127 // The browser's app_name should include the app's ID. 128 EXPECT_NE( 129 new_browser->app_name_.find(extension_app->id()), 130 std::string::npos) << new_browser->app_name_; 131 } 132 133 IN_PROC_BROWSER_TEST_F(BrowserInitTest, OpenAppShortcutWindowPref) { 134 const Extension* extension_app = NULL; 135 LoadApp("app_with_tab_container", &extension_app); 136 ASSERT_FALSE(HasFatalFailure()); // Check for ASSERT failures in LoadApp(). 137 138 // Set a pref indicating that the user wants to open this app in a window. 139 SetAppLaunchPref(extension_app->id(), ExtensionPrefs::LAUNCH_WINDOW); 140 141 CommandLine command_line(CommandLine::NO_PROGRAM); 142 command_line.AppendSwitchASCII(switches::kAppId, extension_app->id()); 143 BrowserInit::LaunchWithProfile launch(FilePath(), command_line); 144 ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), false)); 145 146 // Pref was set to open in a window, so the app should have opened in a 147 // window. The launch should have created a new browser. Find the new 148 // browser. 149 Browser* new_browser = NULL; 150 FindOneOtherBrowser(&new_browser); 151 ASSERT_FALSE(HasFatalFailure()); 152 153 // Expect an app window. 154 EXPECT_EQ(Browser::TYPE_APP, new_browser->type()); 155 156 // The browser's app_name should include the app's ID. 157 EXPECT_NE( 158 new_browser->app_name_.find(extension_app->id()), 159 std::string::npos) << new_browser->app_name_; 160 } 161 162 IN_PROC_BROWSER_TEST_F(BrowserInitTest, OpenAppShortcutTabPref) { 163 // Load an app with launch.container = 'tab'. 164 const Extension* extension_app = NULL; 165 LoadApp("app_with_tab_container", &extension_app); 166 ASSERT_FALSE(HasFatalFailure()); // Check for ASSERT failures in LoadApp(). 167 168 // Set a pref indicating that the user wants to open this app in a window. 169 SetAppLaunchPref(extension_app->id(), ExtensionPrefs::LAUNCH_REGULAR); 170 171 CommandLine command_line(CommandLine::NO_PROGRAM); 172 command_line.AppendSwitchASCII(switches::kAppId, extension_app->id()); 173 BrowserInit::LaunchWithProfile launch(FilePath(), command_line); 174 ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), false)); 175 176 // When an app shortcut is open and the pref indicates a tab should 177 // open, the tab is open in a new browser window. Expect a new window. 178 ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile())); 179 180 Browser* new_browser = NULL; 181 FindOneOtherBrowser(&new_browser); 182 ASSERT_FALSE(HasFatalFailure()); 183 184 // The tab should be in a normal window. 185 EXPECT_EQ(Browser::TYPE_NORMAL, new_browser->type()); 186 187 // The browser's app_name should not include the app's ID: It is in a 188 // normal browser. 189 EXPECT_EQ( 190 new_browser->app_name_.find(extension_app->id()), 191 std::string::npos) << new_browser->app_name_; 192 } 193 194 IN_PROC_BROWSER_TEST_F(BrowserInitTest, OpenAppShortcutPanel) { 195 // Load an app with launch.container = 'panel'. 196 const Extension* extension_app = NULL; 197 LoadApp("app_with_panel_container", &extension_app); 198 ASSERT_FALSE(HasFatalFailure()); // Check for ASSERT failures in LoadApp(). 199 200 CommandLine command_line(CommandLine::NO_PROGRAM); 201 command_line.AppendSwitchASCII(switches::kAppId, extension_app->id()); 202 BrowserInit::LaunchWithProfile launch(FilePath(), command_line); 203 ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), false)); 204 205 // The launch should have created a new browser, with a panel type. 206 Browser* new_browser = NULL; 207 FindOneOtherBrowser(&new_browser); 208 ASSERT_FALSE(HasFatalFailure()); 209 210 // Expect an app panel. 211 EXPECT_EQ(Browser::TYPE_APP_POPUP, new_browser->type()); 212 213 // The new browser's app_name should include the app's ID. 214 EXPECT_NE( 215 new_browser->app_name_.find(extension_app->id()), 216 std::string::npos) << new_browser->app_name_; 217 } 218 219 #endif // !defined(OS_MACOSX) 220