• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <string>
6 
7 #include "base/compiler_specific.h"
8 #include "base/file_path.h"
9 #include "base/sys_info.h"
10 #include "base/utf_string_conversions.h"
11 #include "chrome/app/chrome_command_ids.h"
12 #include "chrome/browser/defaults.h"
13 #include "chrome/browser/extensions/extension_browsertest.h"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/extensions/extension_tab_helper.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/tabs/pinned_tab_codec.h"
18 #include "chrome/browser/tabs/tab_strip_model.h"
19 #include "chrome/browser/translate/translate_tab_helper.h"
20 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
21 #include "chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h"
22 #include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h"
23 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/browser_init.h"
25 #include "chrome/browser/ui/browser_list.h"
26 #include "chrome/browser/ui/browser_navigator.h"
27 #include "chrome/browser/ui/browser_window.h"
28 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
29 #include "chrome/common/chrome_switches.h"
30 #include "chrome/common/extensions/extension.h"
31 #include "chrome/common/url_constants.h"
32 #include "chrome/test/in_process_browser_test.h"
33 #include "chrome/test/ui_test_utils.h"
34 #include "content/browser/renderer_host/render_process_host.h"
35 #include "content/browser/renderer_host/render_view_host.h"
36 #include "content/browser/tab_contents/tab_contents.h"
37 #include "content/common/notification_source.h"
38 #include "content/common/page_transition_types.h"
39 #include "grit/chromium_strings.h"
40 #include "grit/generated_resources.h"
41 #include "net/base/mock_host_resolver.h"
42 #include "net/test/test_server.h"
43 #include "ui/base/l10n/l10n_util.h"
44 
45 #if defined(OS_WIN)
46 #include "base/i18n/rtl.h"
47 #include "chrome/browser/browser_process.h"
48 #endif
49 
50 namespace {
51 
52 const char* kBeforeUnloadHTML =
53     "<html><head><title>beforeunload</title></head><body>"
54     "<script>window.onbeforeunload=function(e){return 'foo'}</script>"
55     "</body></html>";
56 
57 const char* kOpenNewBeforeUnloadPage =
58     "w=window.open(); w.onbeforeunload=function(e){return 'foo'};";
59 
60 const FilePath::CharType* kTitle1File = FILE_PATH_LITERAL("title1.html");
61 const FilePath::CharType* kTitle2File = FILE_PATH_LITERAL("title2.html");
62 
63 const FilePath::CharType kDocRoot[] = FILE_PATH_LITERAL("chrome/test/data");
64 
65 // Given a page title, returns the expected window caption string.
WindowCaptionFromPageTitle(std::wstring page_title)66 std::wstring WindowCaptionFromPageTitle(std::wstring page_title) {
67 #if defined(OS_MACOSX) || defined(OS_CHROMEOS)
68   // On Mac or ChromeOS, we don't want to suffix the page title with
69   // the application name.
70   if (page_title.empty()) {
71     return UTF16ToWideHack(
72         l10n_util::GetStringUTF16(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED));
73   }
74   return page_title;
75 #else
76   if (page_title.empty())
77     return UTF16ToWideHack(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
78 
79   return UTF16ToWideHack(
80       l10n_util::GetStringFUTF16(IDS_BROWSER_WINDOW_TITLE_FORMAT,
81                                  WideToUTF16Hack(page_title)));
82 #endif
83 }
84 
85 // Returns the number of active RenderProcessHosts.
CountRenderProcessHosts()86 int CountRenderProcessHosts() {
87   int result = 0;
88   for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
89        !i.IsAtEnd(); i.Advance())
90     ++result;
91   return result;
92 }
93 
94 class MockTabStripModelObserver : public TabStripModelObserver {
95  public:
MockTabStripModelObserver()96   MockTabStripModelObserver() : closing_count_(0) {}
97 
TabClosingAt(TabStripModel * tab_strip_model,TabContentsWrapper * contents,int index)98   virtual void TabClosingAt(TabStripModel* tab_strip_model,
99                             TabContentsWrapper* contents,
100                             int index) {
101     closing_count_++;
102   }
103 
closing_count() const104   int closing_count() const { return closing_count_; }
105 
106  private:
107   int closing_count_;
108 
109   DISALLOW_COPY_AND_ASSIGN(MockTabStripModelObserver);
110 };
111 
112 // Used by CloseWithAppMenuOpen. Invokes CloseWindow on the supplied browser.
113 class CloseWindowTask : public Task {
114  public:
CloseWindowTask(Browser * browser)115   explicit CloseWindowTask(Browser* browser) : browser_(browser) {}
116 
Run()117   virtual void Run() {
118     browser_->CloseWindow();
119   }
120 
121  private:
122   Browser* browser_;
123 
124   DISALLOW_COPY_AND_ASSIGN(CloseWindowTask);
125 };
126 
127 // Used by CloseWithAppMenuOpen. Posts a CloseWindowTask and shows the app menu.
128 class RunCloseWithAppMenuTask : public Task {
129  public:
RunCloseWithAppMenuTask(Browser * browser)130   explicit RunCloseWithAppMenuTask(Browser* browser) : browser_(browser) {}
131 
Run()132   virtual void Run() {
133     // ShowAppMenu is modal under views. Schedule a task that closes the window.
134     MessageLoop::current()->PostTask(FROM_HERE, new CloseWindowTask(browser_));
135     browser_->ShowAppMenu();
136   }
137 
138  private:
139   Browser* browser_;
140 
141   DISALLOW_COPY_AND_ASSIGN(RunCloseWithAppMenuTask);
142 };
143 
144 }  // namespace
145 
146 class BrowserTest : public ExtensionBrowserTest {
147  protected:
148   // In RTL locales wrap the page title with RTL embedding characters so that it
149   // matches the value returned by GetWindowTitle().
LocaleWindowCaptionFromPageTitle(const std::wstring & expected_title)150   std::wstring LocaleWindowCaptionFromPageTitle(
151       const std::wstring& expected_title) {
152     std::wstring page_title = WindowCaptionFromPageTitle(expected_title);
153 #if defined(OS_WIN)
154     std::string locale = g_browser_process->GetApplicationLocale();
155     if (base::i18n::GetTextDirectionForLocale(locale.c_str()) ==
156         base::i18n::RIGHT_TO_LEFT) {
157       base::i18n::WrapStringWithLTRFormatting(&page_title);
158     }
159 
160     return page_title;
161 #else
162     // Do we need to use the above code on POSIX as well?
163     return page_title;
164 #endif
165   }
166 
167   // Returns the app extension aptly named "App Test".
GetExtension()168   const Extension* GetExtension() {
169     const ExtensionList* extensions =
170         browser()->profile()->GetExtensionService()->extensions();
171     for (size_t i = 0; i < extensions->size(); ++i) {
172       if ((*extensions)[i]->name() == "App Test")
173         return (*extensions)[i];
174     }
175     NOTREACHED();
176     return NULL;
177   }
178 };
179 
180 // Launch the app on a page with no title, check that the app title was set
181 // correctly.
IN_PROC_BROWSER_TEST_F(BrowserTest,NoTitle)182 IN_PROC_BROWSER_TEST_F(BrowserTest, NoTitle) {
183   ui_test_utils::NavigateToURL(browser(),
184       ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
185                                 FilePath(kTitle1File)));
186   EXPECT_EQ(LocaleWindowCaptionFromPageTitle(L"title1.html"),
187             UTF16ToWideHack(browser()->GetWindowTitleForCurrentTab()));
188   string16 tab_title;
189   ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
190   EXPECT_EQ(ASCIIToUTF16("title1.html"), tab_title);
191 }
192 
193 // Launch the app, navigate to a page with a title, check that the app title
194 // was set correctly.
IN_PROC_BROWSER_TEST_F(BrowserTest,Title)195 IN_PROC_BROWSER_TEST_F(BrowserTest, Title) {
196   ui_test_utils::NavigateToURL(browser(),
197       ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
198                                 FilePath(kTitle2File)));
199   const std::wstring test_title(L"Title Of Awesomeness");
200   EXPECT_EQ(LocaleWindowCaptionFromPageTitle(test_title),
201             UTF16ToWideHack(browser()->GetWindowTitleForCurrentTab()));
202   string16 tab_title;
203   ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
204   EXPECT_EQ(WideToUTF16(test_title), tab_title);
205 }
206 
IN_PROC_BROWSER_TEST_F(BrowserTest,JavascriptAlertActivatesTab)207 IN_PROC_BROWSER_TEST_F(BrowserTest, JavascriptAlertActivatesTab) {
208   GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
209                                      FilePath(kTitle1File)));
210   ui_test_utils::NavigateToURL(browser(), url);
211   AddTabAtIndex(0, url, PageTransition::TYPED);
212   EXPECT_EQ(2, browser()->tab_count());
213   EXPECT_EQ(0, browser()->active_index());
214   TabContents* second_tab = browser()->GetTabContentsAt(1);
215   ASSERT_TRUE(second_tab);
216   second_tab->render_view_host()->ExecuteJavascriptInWebFrame(
217       string16(),
218       ASCIIToUTF16("alert('Activate!');"));
219   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
220   alert->CloseModalDialog();
221   EXPECT_EQ(2, browser()->tab_count());
222   EXPECT_EQ(1, browser()->active_index());
223 }
224 
225 
226 
227 #if defined(OS_WIN)
228 // http://crbug.com/75274. On XP crashes inside
229 // URLFetcher::Core::Registry::RemoveURLFetcherCore.
230 #define MAYBE_ThirtyFourTabs FLAKY_ThirtyFourTabs
231 #else
232 #define MAYBE_ThirtyFourTabs ThirtyFourTabs
233 #endif
234 
235 // Create 34 tabs and verify that a lot of processes have been created. The
236 // exact number of processes depends on the amount of memory. Previously we
237 // had a hard limit of 31 processes and this test is mainly directed at
238 // verifying that we don't crash when we pass this limit.
239 // Warning: this test can take >30 seconds when running on a slow (low
240 // memory?) Mac builder.
IN_PROC_BROWSER_TEST_F(BrowserTest,MAYBE_ThirtyFourTabs)241 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_ThirtyFourTabs) {
242   GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
243                                      FilePath(kTitle2File)));
244 
245   // There is one initial tab.
246   for (int ix = 0; ix != 33; ++ix)
247     browser()->AddSelectedTabWithURL(url, PageTransition::TYPED);
248   EXPECT_EQ(34, browser()->tab_count());
249 
250   // See browser\renderer_host\render_process_host.cc for the algorithm to
251   // decide how many processes to create.
252   if (base::SysInfo::AmountOfPhysicalMemoryMB() >= 2048) {
253     EXPECT_GE(CountRenderProcessHosts(), 24);
254   } else {
255     EXPECT_LE(CountRenderProcessHosts(), 23);
256   }
257 }
258 
259 // Test for crbug.com/22004.  Reloading a page with a before unload handler and
260 // then canceling the dialog should not leave the throbber spinning.
IN_PROC_BROWSER_TEST_F(BrowserTest,ReloadThenCancelBeforeUnload)261 IN_PROC_BROWSER_TEST_F(BrowserTest, ReloadThenCancelBeforeUnload) {
262   GURL url(std::string("data:text/html,") + kBeforeUnloadHTML);
263   ui_test_utils::NavigateToURL(browser(), url);
264 
265   // Navigate to another page, but click cancel in the dialog.  Make sure that
266   // the throbber stops spinning.
267   browser()->Reload(CURRENT_TAB);
268   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
269   alert->CloseModalDialog();
270   EXPECT_FALSE(browser()->GetSelectedTabContents()->is_loading());
271 
272   // Clear the beforeunload handler so the test can easily exit.
273   browser()->GetSelectedTabContents()->render_view_host()->
274       ExecuteJavascriptInWebFrame(string16(),
275                                   ASCIIToUTF16("onbeforeunload=null;"));
276 }
277 
278 // Crashy on mac.  http://crbug.com/38522
279 #if defined(OS_MACOSX)
280 #define MAYBE_SingleBeforeUnloadAfterWindowClose \
281         DISABLED_SingleBeforeUnloadAfterWindowClose
282 #else
283 #define MAYBE_SingleBeforeUnloadAfterWindowClose \
284         SingleBeforeUnloadAfterWindowClose
285 #endif
286 
287 // Test for crbug.com/11647.  A page closed with window.close() should not have
288 // two beforeunload dialogs shown.
IN_PROC_BROWSER_TEST_F(BrowserTest,MAYBE_SingleBeforeUnloadAfterWindowClose)289 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_SingleBeforeUnloadAfterWindowClose) {
290   browser()->GetSelectedTabContents()->render_view_host()->
291       ExecuteJavascriptInWebFrame(string16(),
292                                   ASCIIToUTF16(kOpenNewBeforeUnloadPage));
293 
294   // Close the new window with JavaScript, which should show a single
295   // beforeunload dialog.  Then show another alert, to make it easy to verify
296   // that a second beforeunload dialog isn't shown.
297   browser()->GetTabContentsAt(0)->render_view_host()->
298       ExecuteJavascriptInWebFrame(string16(),
299                                   ASCIIToUTF16("w.close(); alert('bar');"));
300   AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
301   alert->native_dialog()->AcceptAppModalDialog();
302 
303   alert = ui_test_utils::WaitForAppModalDialog();
304   EXPECT_FALSE(static_cast<JavaScriptAppModalDialog*>(alert)->
305                    is_before_unload_dialog());
306   alert->native_dialog()->AcceptAppModalDialog();
307 }
308 
309 // Test that get_process_idle_time() returns reasonable values when compared
310 // with time deltas measured locally.
IN_PROC_BROWSER_TEST_F(BrowserTest,RenderIdleTime)311 IN_PROC_BROWSER_TEST_F(BrowserTest, RenderIdleTime) {
312   base::TimeTicks start = base::TimeTicks::Now();
313   ui_test_utils::NavigateToURL(browser(),
314       ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
315                                 FilePath(kTitle1File)));
316   RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
317   for (; !it.IsAtEnd(); it.Advance()) {
318     base::TimeDelta renderer_td =
319         it.GetCurrentValue()->get_child_process_idle_time();
320     base::TimeDelta browser_td = base::TimeTicks::Now() - start;
321     EXPECT_TRUE(browser_td >= renderer_td);
322   }
323 }
324 
325 // Test IDC_CREATE_SHORTCUTS command is enabled for url scheme file, ftp, http
326 // and https and disabled for chrome://, about:// etc.
327 // TODO(pinkerton): Disable app-mode in the model until we implement it
328 // on the Mac. http://crbug.com/13148
329 #if !defined(OS_MACOSX)
IN_PROC_BROWSER_TEST_F(BrowserTest,CommandCreateAppShortcutFile)330 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutFile) {
331   CommandUpdater* command_updater = browser()->command_updater();
332 
333   static const FilePath::CharType* kEmptyFile = FILE_PATH_LITERAL("empty.html");
334   GURL file_url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
335                                           FilePath(kEmptyFile)));
336   ASSERT_TRUE(file_url.SchemeIs(chrome::kFileScheme));
337   ui_test_utils::NavigateToURL(browser(), file_url);
338   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
339 }
340 
IN_PROC_BROWSER_TEST_F(BrowserTest,CommandCreateAppShortcutHttp)341 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutHttp) {
342   CommandUpdater* command_updater = browser()->command_updater();
343 
344   ASSERT_TRUE(test_server()->Start());
345   GURL http_url(test_server()->GetURL(""));
346   ASSERT_TRUE(http_url.SchemeIs(chrome::kHttpScheme));
347   ui_test_utils::NavigateToURL(browser(), http_url);
348   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
349 }
350 
IN_PROC_BROWSER_TEST_F(BrowserTest,CommandCreateAppShortcutHttps)351 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutHttps) {
352   CommandUpdater* command_updater = browser()->command_updater();
353 
354   net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath(kDocRoot));
355   ASSERT_TRUE(test_server.Start());
356   GURL https_url(test_server.GetURL("/"));
357   ASSERT_TRUE(https_url.SchemeIs(chrome::kHttpsScheme));
358   ui_test_utils::NavigateToURL(browser(), https_url);
359   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
360 }
361 
IN_PROC_BROWSER_TEST_F(BrowserTest,CommandCreateAppShortcutFtp)362 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutFtp) {
363   CommandUpdater* command_updater = browser()->command_updater();
364 
365   net::TestServer test_server(net::TestServer::TYPE_FTP, FilePath(kDocRoot));
366   ASSERT_TRUE(test_server.Start());
367   GURL ftp_url(test_server.GetURL(""));
368   ASSERT_TRUE(ftp_url.SchemeIs(chrome::kFtpScheme));
369   ui_test_utils::NavigateToURL(browser(), ftp_url);
370   EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
371 }
372 
IN_PROC_BROWSER_TEST_F(BrowserTest,CommandCreateAppShortcutInvalid)373 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutInvalid) {
374   CommandUpdater* command_updater = browser()->command_updater();
375 
376   // Urls that should not have shortcuts.
377   GURL new_tab_url(chrome::kChromeUINewTabURL);
378   ui_test_utils::NavigateToURL(browser(), new_tab_url);
379   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
380 
381   GURL history_url(chrome::kChromeUIHistoryURL);
382   ui_test_utils::NavigateToURL(browser(), history_url);
383   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
384 
385   GURL downloads_url(chrome::kChromeUIDownloadsURL);
386   ui_test_utils::NavigateToURL(browser(), downloads_url);
387   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
388 
389   GURL blank_url(chrome::kAboutBlankURL);
390   ui_test_utils::NavigateToURL(browser(), blank_url);
391   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
392 }
393 
394 // Change a tab into an application window.
395 // DISABLED: http://crbug.com/72310
IN_PROC_BROWSER_TEST_F(BrowserTest,DISABLED_ConvertTabToAppShortcut)396 IN_PROC_BROWSER_TEST_F(BrowserTest, DISABLED_ConvertTabToAppShortcut) {
397   ASSERT_TRUE(test_server()->Start());
398   GURL http_url(test_server()->GetURL(""));
399   ASSERT_TRUE(http_url.SchemeIs(chrome::kHttpScheme));
400 
401   ASSERT_EQ(1, browser()->tab_count());
402   TabContents* initial_tab = browser()->GetTabContentsAt(0);
403   TabContents* app_tab = browser()->AddSelectedTabWithURL(
404       http_url, PageTransition::TYPED)->tab_contents();
405   ASSERT_EQ(2, browser()->tab_count());
406   ASSERT_EQ(1u, BrowserList::GetBrowserCount(browser()->profile()));
407 
408   // Normal tabs should accept load drops.
409   EXPECT_TRUE(initial_tab->GetMutableRendererPrefs()->can_accept_load_drops);
410   EXPECT_TRUE(app_tab->GetMutableRendererPrefs()->can_accept_load_drops);
411 
412   // Turn |app_tab| into a tab in an app panel.
413   browser()->ConvertContentsToApplication(app_tab);
414 
415   // The launch should have created a new browser.
416   ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile()));
417 
418   // Find the new browser.
419   Browser* app_browser = NULL;
420   for (BrowserList::const_iterator i = BrowserList::begin();
421        i != BrowserList::end() && !app_browser; ++i) {
422     if (*i != browser())
423       app_browser = *i;
424   }
425   ASSERT_TRUE(app_browser);
426 
427   // Check that the tab contents is in the new browser, and not in the old.
428   ASSERT_EQ(1, browser()->tab_count());
429   ASSERT_EQ(initial_tab, browser()->GetTabContentsAt(0));
430 
431   // Check that the appliaction browser has a single tab, and that tab contains
432   // the content that we app-ified.
433   ASSERT_EQ(1, app_browser->tab_count());
434   ASSERT_EQ(app_tab, app_browser->GetTabContentsAt(0));
435 
436   // Normal tabs should accept load drops.
437   EXPECT_TRUE(initial_tab->GetMutableRendererPrefs()->can_accept_load_drops);
438 
439   // The tab in an app window should not.
440   EXPECT_FALSE(app_tab->GetMutableRendererPrefs()->can_accept_load_drops);
441 }
442 
443 #endif  // !defined(OS_MACOSX)
444 
445 // Test RenderView correctly send back favicon url for web page that redirects
446 // to an anchor in javascript body.onload handler.
IN_PROC_BROWSER_TEST_F(BrowserTest,FaviconOfOnloadRedirectToAnchorPage)447 IN_PROC_BROWSER_TEST_F(BrowserTest, FaviconOfOnloadRedirectToAnchorPage) {
448   ASSERT_TRUE(test_server()->Start());
449   GURL url(test_server()->GetURL("files/onload_redirect_to_anchor.html"));
450   GURL expected_favicon_url(test_server()->GetURL("files/test.png"));
451 
452   ui_test_utils::NavigateToURL(browser(), url);
453 
454   NavigationEntry* entry = browser()->GetSelectedTabContents()->
455       controller().GetActiveEntry();
456   EXPECT_EQ(expected_favicon_url.spec(), entry->favicon().url().spec());
457 }
458 
459 // Test that an icon can be changed from JS.
IN_PROC_BROWSER_TEST_F(BrowserTest,FaviconChange)460 IN_PROC_BROWSER_TEST_F(BrowserTest, FaviconChange) {
461   static const FilePath::CharType* kFile =
462       FILE_PATH_LITERAL("onload_change_favicon.html");
463   GURL file_url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
464                                           FilePath(kFile)));
465   ASSERT_TRUE(file_url.SchemeIs(chrome::kFileScheme));
466   ui_test_utils::NavigateToURL(browser(), file_url);
467 
468   NavigationEntry* entry = browser()->GetSelectedTabContents()->
469       controller().GetActiveEntry();
470   static const FilePath::CharType* kIcon =
471       FILE_PATH_LITERAL("test1.png");
472   GURL expected_favicon_url(
473       ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
474                                          FilePath(kIcon)));
475   EXPECT_EQ(expected_favicon_url.spec(), entry->favicon().url().spec());
476 }
477 
478 // Makes sure TabClosing is sent when uninstalling an extension that is an app
479 // tab.
IN_PROC_BROWSER_TEST_F(BrowserTest,TabClosingWhenRemovingExtension)480 IN_PROC_BROWSER_TEST_F(BrowserTest, TabClosingWhenRemovingExtension) {
481   ASSERT_TRUE(test_server()->Start());
482   host_resolver()->AddRule("www.example.com", "127.0.0.1");
483   GURL url(test_server()->GetURL("empty.html"));
484   TabStripModel* model = browser()->tabstrip_model();
485 
486   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/")));
487 
488   const Extension* extension_app = GetExtension();
489 
490   ui_test_utils::NavigateToURL(browser(), url);
491 
492   TabContentsWrapper* app_contents =
493       Browser::TabContentsFactory(browser()->profile(), NULL,
494                                   MSG_ROUTING_NONE, NULL, NULL);
495   app_contents->extension_tab_helper()->SetExtensionApp(extension_app);
496 
497   model->AddTabContents(app_contents, 0, 0, TabStripModel::ADD_NONE);
498   model->SetTabPinned(0, true);
499   ui_test_utils::NavigateToURL(browser(), url);
500 
501   MockTabStripModelObserver observer;
502   model->AddObserver(&observer);
503 
504   // Uninstall the extension and make sure TabClosing is sent.
505   ExtensionService* service = browser()->profile()->GetExtensionService();
506   service->UninstallExtension(GetExtension()->id(), false, NULL);
507   EXPECT_EQ(1, observer.closing_count());
508 
509   model->RemoveObserver(&observer);
510 
511   // There should only be one tab now.
512   ASSERT_EQ(1, browser()->tab_count());
513 }
514 
515 #if !defined(OS_MACOSX)
516 // Open with --app-id=<id>, and see that an app window opens.
IN_PROC_BROWSER_TEST_F(BrowserTest,AppIdSwitch)517 IN_PROC_BROWSER_TEST_F(BrowserTest, AppIdSwitch) {
518   ASSERT_TRUE(test_server()->Start());
519 
520   // Load an app.
521   host_resolver()->AddRule("www.example.com", "127.0.0.1");
522   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/")));
523   const Extension* extension_app = GetExtension();
524 
525   CommandLine command_line(CommandLine::NO_PROGRAM);
526   command_line.AppendSwitchASCII(switches::kAppId, extension_app->id());
527 
528   BrowserInit::LaunchWithProfile launch(FilePath(), command_line);
529   ASSERT_TRUE(launch.OpenApplicationWindow(browser()->profile()));
530 
531   // Check that the new browser has an app name.
532   // The launch should have created a new browser.
533   ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile()));
534 
535   // Find the new browser.
536   Browser* new_browser = NULL;
537   for (BrowserList::const_iterator i = BrowserList::begin();
538        i != BrowserList::end() && !new_browser; ++i) {
539     if (*i != browser())
540       new_browser = *i;
541   }
542   ASSERT_TRUE(new_browser);
543   ASSERT_TRUE(new_browser != browser());
544 
545   // The browser's app_name should include the app's ID.
546   ASSERT_NE(
547       new_browser->app_name_.find(extension_app->id()),
548       std::string::npos) << new_browser->app_name_;
549 
550 }
551 #endif
552 
553 #if defined(OS_WIN)
554 // http://crbug.com/46198. On XP/Vista, the failure rate is 5 ~ 6%.
555 #define MAYBE_PageLanguageDetection FLAKY_PageLanguageDetection
556 #else
557 #define MAYBE_PageLanguageDetection PageLanguageDetection
558 #endif
559 // Tests that the CLD (Compact Language Detection) works properly.
IN_PROC_BROWSER_TEST_F(BrowserTest,MAYBE_PageLanguageDetection)560 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_PageLanguageDetection) {
561   ASSERT_TRUE(test_server()->Start());
562 
563   TabContents* current_tab = browser()->GetSelectedTabContents();
564   TabContentsWrapper* wrapper = browser()->GetSelectedTabContentsWrapper();
565   TranslateTabHelper* helper = wrapper->translate_tab_helper();
566   Source<TabContents> source(current_tab);
567 
568   // Navigate to a page in English.
569   ui_test_utils::WindowedNotificationObserverWithDetails<std::string>
570       en_language_detected_signal(NotificationType::TAB_LANGUAGE_DETERMINED,
571                                   source);
572   ui_test_utils::NavigateToURL(
573       browser(), GURL(test_server()->GetURL("files/english_page.html")));
574   EXPECT_TRUE(helper->language_state().original_language().empty());
575   en_language_detected_signal.Wait();
576   std::string lang;
577   EXPECT_TRUE(en_language_detected_signal.GetDetailsFor(
578         source.map_key(), &lang));
579   EXPECT_EQ("en", lang);
580   EXPECT_EQ("en", helper->language_state().original_language());
581 
582   // Now navigate to a page in French.
583   ui_test_utils::WindowedNotificationObserverWithDetails<std::string>
584       fr_language_detected_signal(NotificationType::TAB_LANGUAGE_DETERMINED,
585                                   source);
586   ui_test_utils::NavigateToURL(
587       browser(), GURL(test_server()->GetURL("files/french_page.html")));
588   EXPECT_TRUE(helper->language_state().original_language().empty());
589   fr_language_detected_signal.Wait();
590   lang.clear();
591   EXPECT_TRUE(fr_language_detected_signal.GetDetailsFor(
592         source.map_key(), &lang));
593   EXPECT_EQ("fr", lang);
594   EXPECT_EQ("fr", helper->language_state().original_language());
595 }
596 
597 // Chromeos defaults to restoring the last session, so this test isn't
598 // applicable.
599 #if !defined(OS_CHROMEOS)
600 #if defined(OS_MACOSX)
601 // Crashy, http://crbug.com/38522
602 #define RestorePinnedTabs DISABLED_RestorePinnedTabs
603 #endif
604 // Makes sure pinned tabs are restored correctly on start.
IN_PROC_BROWSER_TEST_F(BrowserTest,RestorePinnedTabs)605 IN_PROC_BROWSER_TEST_F(BrowserTest, RestorePinnedTabs) {
606   ASSERT_TRUE(test_server()->Start());
607 
608   // Add an pinned app tab.
609   host_resolver()->AddRule("www.example.com", "127.0.0.1");
610   GURL url(test_server()->GetURL("empty.html"));
611   TabStripModel* model = browser()->tabstrip_model();
612   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/")));
613   const Extension* extension_app = GetExtension();
614   ui_test_utils::NavigateToURL(browser(), url);
615   TabContentsWrapper* app_contents =
616     Browser::TabContentsFactory(browser()->profile(), NULL,
617                                 MSG_ROUTING_NONE, NULL, NULL);
618   app_contents->extension_tab_helper()->SetExtensionApp(extension_app);
619   model->AddTabContents(app_contents, 0, 0, TabStripModel::ADD_NONE);
620   model->SetTabPinned(0, true);
621   ui_test_utils::NavigateToURL(browser(), url);
622 
623   // Add a non pinned tab.
624   browser()->NewTab();
625 
626   // Add a pinned non-app tab.
627   browser()->NewTab();
628   ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
629   model->SetTabPinned(2, true);
630 
631   // Write out the pinned tabs.
632   PinnedTabCodec::WritePinnedTabs(browser()->profile());
633 
634   // Simulate launching again.
635   CommandLine dummy(CommandLine::NO_PROGRAM);
636   BrowserInit::LaunchWithProfile launch(FilePath(), dummy);
637   launch.profile_ = browser()->profile();
638   launch.ProcessStartupURLs(std::vector<GURL>());
639 
640   // The launch should have created a new browser.
641   ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile()));
642 
643   // Find the new browser.
644   Browser* new_browser = NULL;
645   for (BrowserList::const_iterator i = BrowserList::begin();
646        i != BrowserList::end() && !new_browser; ++i) {
647     if (*i != browser())
648       new_browser = *i;
649   }
650   ASSERT_TRUE(new_browser);
651   ASSERT_TRUE(new_browser != browser());
652 
653   // We should get back an additional tab for the app, and another for the
654   // default home page.
655   ASSERT_EQ(3, new_browser->tab_count());
656 
657   // Make sure the state matches.
658   TabStripModel* new_model = new_browser->tabstrip_model();
659   EXPECT_TRUE(new_model->IsAppTab(0));
660   EXPECT_FALSE(new_model->IsAppTab(1));
661   EXPECT_FALSE(new_model->IsAppTab(2));
662 
663   EXPECT_TRUE(new_model->IsTabPinned(0));
664   EXPECT_TRUE(new_model->IsTabPinned(1));
665   EXPECT_FALSE(new_model->IsTabPinned(2));
666 
667   EXPECT_EQ(browser()->GetHomePage(),
668       new_model->GetTabContentsAt(2)->tab_contents()->GetURL());
669 
670   EXPECT_TRUE(
671       new_model->GetTabContentsAt(0)->extension_tab_helper()->extension_app() ==
672           extension_app);
673 }
674 #endif  // !defined(OS_CHROMEOS)
675 
676 // This test verifies we don't crash when closing the last window and the app
677 // menu is showing.
IN_PROC_BROWSER_TEST_F(BrowserTest,CloseWithAppMenuOpen)678 IN_PROC_BROWSER_TEST_F(BrowserTest, CloseWithAppMenuOpen) {
679   if (browser_defaults::kBrowserAliveWithNoWindows)
680     return;
681 
682   // We need a message loop running for menus on windows.
683   MessageLoop::current()->PostTask(FROM_HERE,
684                                    new RunCloseWithAppMenuTask(browser()));
685 }
686 
687 #if !defined(OS_MACOSX)
IN_PROC_BROWSER_TEST_F(BrowserTest,OpenAppWindowLikeNtp)688 IN_PROC_BROWSER_TEST_F(BrowserTest, OpenAppWindowLikeNtp) {
689   ASSERT_TRUE(test_server()->Start());
690 
691   // Load an app
692   host_resolver()->AddRule("www.example.com", "127.0.0.1");
693   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/")));
694   const Extension* extension_app = GetExtension();
695 
696   // Launch it in a window, as AppLauncherHandler::HandleLaunchApp() would.
697   TabContents* app_window = Browser::OpenApplication(
698       browser()->profile(), extension_app, extension_misc::LAUNCH_WINDOW, NULL);
699   ASSERT_TRUE(app_window);
700 
701   // Apps launched in a window from the NTP do not have extension_app set in
702   // tab contents.
703   TabContentsWrapper* wrapper =
704           TabContentsWrapper::GetCurrentWrapperForContents(app_window);
705   EXPECT_FALSE(wrapper->extension_tab_helper()->extension_app());
706   EXPECT_EQ(extension_app->GetFullLaunchURL(), app_window->GetURL());
707 
708   // The launch should have created a new browser.
709   ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile()));
710 
711   // Find the new browser.
712   Browser* new_browser = NULL;
713   for (BrowserList::const_iterator i = BrowserList::begin();
714        i != BrowserList::end() && !new_browser; ++i) {
715     if (*i != browser())
716       new_browser = *i;
717   }
718   ASSERT_TRUE(new_browser);
719   ASSERT_TRUE(new_browser != browser());
720 
721   EXPECT_EQ(Browser::TYPE_APP, new_browser->type());
722 
723   // The browser's app name should include the extension's id.
724   std::string app_name = new_browser->app_name_;
725   EXPECT_NE(app_name.find(extension_app->id()), std::string::npos)
726       << "Name " << app_name << " should contain id "<< extension_app->id();
727 }
728 #endif  // !defined(OS_MACOSX)
729 
730 // TODO(ben): this test was never enabled. It has bit-rotted since being added.
731 // It originally lived in browser_unittest.cc, but has been moved here to make
732 // room for real browser unit tests.
733 #if 0
734 class BrowserTest2 : public InProcessBrowserTest {
735  public:
736   BrowserTest2() {
737     host_resolver_proc_ = new net::RuleBasedHostResolverProc(NULL);
738     // Avoid making external DNS lookups. In this test we don't need this
739     // to succeed.
740     host_resolver_proc_->AddSimulatedFailure("*.google.com");
741     scoped_host_resolver_proc_.Init(host_resolver_proc_.get());
742   }
743 
744  private:
745   scoped_refptr<net::RuleBasedHostResolverProc> host_resolver_proc_;
746   net::ScopedDefaultHostResolverProc scoped_host_resolver_proc_;
747 };
748 
749 IN_PROC_BROWSER_TEST_F(BrowserTest2, NoTabsInPopups) {
750   Browser::RegisterAppPrefs(L"Test");
751 
752   // We start with a normal browser with one tab.
753   EXPECT_EQ(1, browser()->tab_count());
754 
755   // Open a popup browser with a single blank foreground tab.
756   Browser* popup_browser = browser()->CreateForType(Browser::TYPE_POPUP,
757                                                     browser()->profile());
758   popup_browser->AddBlankTab(true);
759   EXPECT_EQ(1, popup_browser->tab_count());
760 
761   // Now try opening another tab in the popup browser.
762   AddTabWithURLParams params1(url, PageTransition::TYPED);
763   popup_browser->AddTabWithURL(&params1);
764   EXPECT_EQ(popup_browser, params1.target);
765 
766   // The popup should still only have one tab.
767   EXPECT_EQ(1, popup_browser->tab_count());
768 
769   // The normal browser should now have two.
770   EXPECT_EQ(2, browser()->tab_count());
771 
772   // Open an app frame browser with a single blank foreground tab.
773   Browser* app_browser =
774       browser()->CreateForApp(L"Test", browser()->profile(), false);
775   app_browser->AddBlankTab(true);
776   EXPECT_EQ(1, app_browser->tab_count());
777 
778   // Now try opening another tab in the app browser.
779   AddTabWithURLParams params2(GURL(chrome::kAboutBlankURL),
780                               PageTransition::TYPED);
781   app_browser->AddTabWithURL(&params2);
782   EXPECT_EQ(app_browser, params2.target);
783 
784   // The popup should still only have one tab.
785   EXPECT_EQ(1, app_browser->tab_count());
786 
787   // The normal browser should now have three.
788   EXPECT_EQ(3, browser()->tab_count());
789 
790   // Open an app frame popup browser with a single blank foreground tab.
791   Browser* app_popup_browser =
792       browser()->CreateForApp(L"Test", browser()->profile(), false);
793   app_popup_browser->AddBlankTab(true);
794   EXPECT_EQ(1, app_popup_browser->tab_count());
795 
796   // Now try opening another tab in the app popup browser.
797   AddTabWithURLParams params3(GURL(chrome::kAboutBlankURL),
798                               PageTransition::TYPED);
799   app_popup_browser->AddTabWithURL(&params3);
800   EXPECT_EQ(app_popup_browser, params3.target);
801 
802   // The popup should still only have one tab.
803   EXPECT_EQ(1, app_popup_browser->tab_count());
804 
805   // The normal browser should now have four.
806   EXPECT_EQ(4, browser()->tab_count());
807 
808   // Close the additional browsers.
809   popup_browser->CloseAllTabs();
810   app_browser->CloseAllTabs();
811   app_popup_browser->CloseAllTabs();
812 }
813 #endif
814