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 "chrome/browser/extensions/extension_apitest.h" 6 #include "chrome/browser/extensions/extension_service.h" 7 #include "chrome/browser/extensions/extension_web_ui.h" 8 #include "chrome/browser/prefs/pref_service.h" 9 #include "chrome/browser/prefs/scoped_user_pref_update.h" 10 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/ui/browser.h" 12 #include "chrome/browser/ui/browser_list.h" 13 #include "chrome/common/url_constants.h" 14 #include "chrome/test/ui_test_utils.h" 15 #include "content/browser/tab_contents/tab_contents.h" 16 17 class ExtensionOverrideTest : public ExtensionApiTest { 18 protected: 19 bool CheckHistoryOverridesContainsNoDupes() { 20 // There should be no duplicate entries in the preferences. 21 const DictionaryValue* overrides = 22 browser()->profile()->GetPrefs()->GetDictionary( 23 ExtensionWebUI::kExtensionURLOverrides); 24 25 ListValue* values = NULL; 26 if (!overrides->GetList("history", &values)) 27 return false; 28 29 std::set<std::string> seen_overrides; 30 for (size_t i = 0; i < values->GetSize(); ++i) { 31 std::string value; 32 if (!values->GetString(i, &value)) 33 return false; 34 35 if (seen_overrides.find(value) != seen_overrides.end()) 36 return false; 37 38 seen_overrides.insert(value); 39 } 40 41 return true; 42 } 43 44 #if defined(TOUCH_UI) 45 // Navigate to the keyboard page, and ensure we have arrived at an 46 // extension URL. 47 void NavigateToKeyboard() { 48 ui_test_utils::NavigateToURL(browser(), GURL("chrome://keyboard/")); 49 TabContents* tab = browser()->GetSelectedTabContents(); 50 ASSERT_TRUE(tab->controller().GetActiveEntry()); 51 EXPECT_TRUE(tab->controller().GetActiveEntry()->url(). 52 SchemeIs(chrome::kExtensionScheme)); 53 } 54 #endif 55 }; 56 57 IN_PROC_BROWSER_TEST_F(ExtensionOverrideTest, OverrideNewtab) { 58 ASSERT_TRUE(RunExtensionTest("override/newtab")) << message_; 59 { 60 ResultCatcher catcher; 61 // Navigate to the new tab page. The overridden new tab page 62 // will call chrome.test.notifyPass() . 63 ui_test_utils::NavigateToURL(browser(), GURL("chrome://newtab/")); 64 TabContents* tab = browser()->GetSelectedTabContents(); 65 ASSERT_TRUE(tab->controller().GetActiveEntry()); 66 EXPECT_TRUE(tab->controller().GetActiveEntry()->url(). 67 SchemeIs(chrome::kExtensionScheme)); 68 69 ASSERT_TRUE(catcher.GetNextResult()); 70 } 71 72 // TODO(erikkay) Load a second extension with the same override. 73 // Verify behavior, then unload the first and verify behavior, etc. 74 } 75 76 #if defined(OS_MACOSX) 77 // Hangy: http://crbug.com/70511 78 #define MAYBE_OverrideNewtabIncognito DISABLED_OverrideNewtabIncognito 79 #else 80 #define MAYBE_OverrideNewtabIncognito OverrideNewtabIncognito 81 #endif 82 IN_PROC_BROWSER_TEST_F(ExtensionOverrideTest, MAYBE_OverrideNewtabIncognito) { 83 ASSERT_TRUE(RunExtensionTest("override/newtab")) << message_; 84 85 // Navigate an incognito tab to the new tab page. We should get the actual 86 // new tab page because we can't load chrome-extension URLs in incognito. 87 ui_test_utils::OpenURLOffTheRecord(browser()->profile(), 88 GURL("chrome://newtab/")); 89 Browser* otr_browser = BrowserList::FindBrowserWithType( 90 browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL, 91 false); 92 TabContents* tab = otr_browser->GetSelectedTabContents(); 93 ASSERT_TRUE(tab->controller().GetActiveEntry()); 94 EXPECT_FALSE(tab->controller().GetActiveEntry()->url(). 95 SchemeIs(chrome::kExtensionScheme)); 96 } 97 98 // Times out consistently on Win, http://crbug.com/45173. 99 #if defined(OS_WIN) 100 #define MAYBE_OverrideHistory DISABLED_OverrideHistory 101 #else 102 #define MAYBE_OverrideHistory OverrideHistory 103 #endif // defined(OS_WIN) 104 105 IN_PROC_BROWSER_TEST_F(ExtensionOverrideTest, MAYBE_OverrideHistory) { 106 ASSERT_TRUE(RunExtensionTest("override/history")) << message_; 107 { 108 ResultCatcher catcher; 109 // Navigate to the history page. The overridden history page 110 // will call chrome.test.notifyPass() . 111 ui_test_utils::NavigateToURL(browser(), GURL("chrome://history/")); 112 ASSERT_TRUE(catcher.GetNextResult()); 113 } 114 } 115 116 // Regression test for http://crbug.com/41442. 117 IN_PROC_BROWSER_TEST_F(ExtensionOverrideTest, ShouldNotCreateDuplicateEntries) { 118 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("override/history"))); 119 120 // Simulate several LoadExtension() calls happening over the lifetime of 121 // a preferences file without corresponding UnloadExtension() calls. 122 for (size_t i = 0; i < 3; ++i) { 123 ExtensionWebUI::RegisterChromeURLOverrides( 124 browser()->profile(), 125 browser()->profile()->GetExtensionService()->extensions()->back()-> 126 GetChromeURLOverrides()); 127 } 128 129 ASSERT_TRUE(CheckHistoryOverridesContainsNoDupes()); 130 } 131 132 IN_PROC_BROWSER_TEST_F(ExtensionOverrideTest, ShouldCleanUpDuplicateEntries) { 133 // Simulate several LoadExtension() calls happening over the lifetime of 134 // a preferences file without corresponding UnloadExtension() calls. This is 135 // the same as the above test, except for that it is testing the case where 136 // the file already contains dupes when an extension is loaded. 137 ListValue* list = new ListValue(); 138 for (size_t i = 0; i < 3; ++i) 139 list->Append(Value::CreateStringValue("http://www.google.com/")); 140 141 { 142 DictionaryPrefUpdate update(browser()->profile()->GetPrefs(), 143 ExtensionWebUI::kExtensionURLOverrides); 144 update.Get()->Set("history", list); 145 } 146 147 ASSERT_FALSE(CheckHistoryOverridesContainsNoDupes()); 148 149 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("override/history"))); 150 151 ASSERT_TRUE(CheckHistoryOverridesContainsNoDupes()); 152 } 153 154 #if defined(TOUCH_UI) 155 IN_PROC_BROWSER_TEST_F(ExtensionOverrideTest, OverrideKeyboard) { 156 ASSERT_TRUE(RunExtensionTest("override/keyboard")) << message_; 157 { 158 ResultCatcher catcher; 159 NavigateToKeyboard(); 160 ASSERT_TRUE(catcher.GetNextResult()); 161 } 162 163 // Load the failing version. This should take precedence. 164 ASSERT_TRUE(LoadExtension( 165 test_data_dir_.AppendASCII("override").AppendASCII("keyboard_fails"))); 166 { 167 ResultCatcher catcher; 168 NavigateToKeyboard(); 169 ASSERT_FALSE(catcher.GetNextResult()); 170 } 171 172 // Unload the failing version. We should be back to passing now. 173 const ExtensionList *extensions = 174 browser()->profile()->GetExtensionService()->extensions(); 175 UnloadExtension((*extensions->rbegin())->id()); 176 { 177 ResultCatcher catcher; 178 NavigateToKeyboard(); 179 ASSERT_TRUE(catcher.GetNextResult()); 180 } 181 } 182 #endif 183