#!/usr/bin/env python # Copyright (c) 2011 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. import glob import os import re import shutil import tempfile import urlparse import pyauto_functional # Must be imported before pyauto import pyauto import test_utils class OmniboxTest(pyauto.PyUITest): """Test cases for the omnibox.""" def Debug(self): """Test method for experimentation. This method will not run automatically. """ import time while True: self.pprint(self.GetOmniboxInfo().omniboxdict) time.sleep(1) def testFocusOnStartup(self): """Verify that the omnibox has focus on startup.""" self.WaitUntilOmniboxReadyHack() self.assertTrue(self.GetOmniboxInfo().Properties('has_focus')) def testHistoryResult(self): """Verify that the omnibox can fetch items from the history.""" url = self.GetFileURLForDataPath('title2.html') title = 'Title Of Awesomeness' self.AppendTab(pyauto.GURL(url)) def _VerifyHistoryResult(query_list, description, windex=0): """Verify result matching given description for given list of queries.""" for query_text in query_list: matches = test_utils.GetOmniboxMatchesFor( self, query_text, windex=windex, attr_dict={'description': description}) self.assertTrue(matches) self.assertEqual(1, len(matches)) item = matches[0] self.assertEqual(url, item['destination_url']) # Query using URL & title. _VerifyHistoryResult([url, title], title) # Verify results in another tab. self.AppendTab(pyauto.GURL()) _VerifyHistoryResult([url, title], title) # Verify results in another window. self.OpenNewBrowserWindow(True) self.WaitUntilOmniboxReadyHack(windex=1) _VerifyHistoryResult([url, title], title, windex=1) # Verify results in an incognito window. self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW) self.WaitUntilOmniboxReadyHack(windex=2) _VerifyHistoryResult([url, title], title, windex=2) def _VerifyOmniboxURLMatches(self, url, description, windex=0): """Verify URL match results from the omnibox. Args: url: The URL to use. description: The string description within the history page and Google search to match against. windex: The window index to work on. Defaults to 0 (first window). """ matches_description = test_utils.GetOmniboxMatchesFor( self, url, windex=windex, attr_dict={'description': description}) self.assertEqual(1, len(matches_description)) if description == 'Google Search': self.assertTrue(re.match('http://www.google.com/search.+', matches_description[0]['destination_url'])) else: self.assertEqual(url, matches_description[0]['destination_url']) def testFetchHistoryResultItems(self): """Verify omnibox fetches history items in 2nd tab, window and incognito.""" url = self.GetFileURLForDataPath('title2.html') title = 'Title Of Awesomeness' desc = 'Google Search' # Fetch history page item in the second tab. self.AppendTab(pyauto.GURL(url)) self._VerifyOmniboxURLMatches(url, title) # Fetch history page items in the second window. self.OpenNewBrowserWindow(True) self.NavigateToURL(url, 1, 0) self._VerifyOmniboxURLMatches(url, title, windex=1) # Fetch google search items in incognito window. self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW) self.NavigateToURL(url, 2, 0) self._VerifyOmniboxURLMatches(url, desc, windex=2) def testSelect(self): """Verify omnibox popup selection.""" url1 = self.GetFileURLForDataPath('title2.html') url2 = self.GetFileURLForDataPath('title1.html') title1 = 'Title Of Awesomeness' self.NavigateToURL(url1) self.NavigateToURL(url2) matches = test_utils.GetOmniboxMatchesFor(self, 'file://') self.assertTrue(matches) # Find the index of match for |url1|. index = None for i, match in enumerate(matches): if match['description'] == title1: index = i self.assertTrue(index is not None) self.OmniboxMovePopupSelection(index) # Select |url1| line in popup. self.assertEqual(url1, self.GetOmniboxInfo().Text()) self.OmniboxAcceptInput() self.assertEqual(title1, self.GetActiveTabTitle()) def testGoogleSearch(self): """Verify Google search item in omnibox results.""" search_text = 'hello world' verify_str = 'Google Search' url_re = 'http://www.google.com/search\?.*q=hello\+world.*' matches_description = test_utils.GetOmniboxMatchesFor( self, search_text, attr_dict={'description': verify_str}) self.assertTrue(matches_description) # There should be a least one entry with the description Google. Suggest # results may end up having 'Google Search' in them, so use >=. self.assertTrue(len(matches_description) >= 1) item = matches_description[0] self.assertTrue(re.search(url_re, item['destination_url'])) self.assertEqual('search-what-you-typed', item['type']) def testInlineAutoComplete(self): """Verify inline autocomplete for a pre-visited URL.""" self.NavigateToURL('http://www.google.com') matches = test_utils.GetOmniboxMatchesFor(self, 'goog') self.assertTrue(matches) # Omnibox should suggest auto completed URL as the first item. matches_description = matches[0] self.assertTrue('www.google.com' in matches_description['contents']) self.assertEqual('history-url', matches_description['type']) # The URL should be inline-autocompleted in the omnibox. self.assertTrue('google.com' in self.GetOmniboxInfo().Text()) def testCrazyFilenames(self): """Test omnibox query with filenames containing special chars. The files are created on the fly and cleaned after use. """ filename = os.path.join(self.DataDir(), 'downloads', 'crazy_filenames.txt') zip_names = self.EvalDataFrom(filename) # We got .zip filenames. Change them to .html. crazy_filenames = [x.replace('.zip', '.html') for x in zip_names] title = 'given title' def _CreateFile(name): """Create the given html file.""" fp = open(name, 'w') # |name| could be unicode. print >>fp, '<html><title>%s</title><body>' % title print >>fp, 'This is a junk file named <h2>%s</h2>' % repr(name) print >>fp, '</body></html>' fp.close() crazy_fileurls = [] # Temp dir for hosting crazy filenames. temp_dir = tempfile.mkdtemp(prefix='omnibox') # Windows has a dual nature dealing with unicode filenames. # While the files are internally saved as unicode, there's a non-unicode # aware API that returns a locale-dependent coding on the true unicode # filenames. This messes up things. # Filesystem-interfacing functions like os.listdir() need to # be given unicode strings to "do the right thing" on win. # Ref: http://boodebr.org/main/python/all-about-python-and-unicode try: for filename in crazy_filenames: # |filename| is unicode. file_path = os.path.join(temp_dir, filename.encode('utf-8')) _CreateFile(os.path.join(temp_dir, filename)) file_url = self.GetFileURLForPath(file_path) crazy_fileurls.append(file_url) self.NavigateToURL(file_url) # Verify omnibox queries. for file_url in crazy_fileurls: matches = test_utils.GetOmniboxMatchesFor(self, file_url, attr_dict={'type': 'url-what-you-typed', 'description': title}) self.assertTrue(matches) self.assertEqual(1, len(matches)) self.assertTrue(os.path.basename(file_url) in matches[0]['destination_url']) finally: shutil.rmtree(unicode(temp_dir)) # Unicode so that Win treats nicely. def testSuggest(self): """Verify suggested results in omnibox.""" matches = test_utils.GetOmniboxMatchesFor(self, 'apple') self.assertTrue(matches) self.assertTrue([x for x in matches if x['type'] == 'search-suggest']) def testDifferentTypesOfResults(self): """Verify different types of results from omnibox. This includes history result, bookmark result, suggest results. """ url = 'http://www.google.com/' title = 'Google' search_string = 'google' self.AddBookmarkURL( # Add a bookmark. self.GetBookmarkModel().BookmarkBar()['id'], 0, title, url) self.NavigateToURL(url) # Build up history. matches = test_utils.GetOmniboxMatchesFor(self, search_string) self.assertTrue(matches) # Verify starred result (indicating bookmarked url). self.assertTrue([x for x in matches if x['starred'] == True]) for item_type in ('history-url', 'search-what-you-typed', 'search-suggest',): self.assertTrue([x for x in matches if x['type'] == item_type]) def testSuggestPref(self): """Verify no suggests for omnibox when suggested-services disabled.""" search_string = 'apple' self.assertTrue(self.GetPrefsInfo().Prefs(pyauto.kSearchSuggestEnabled)) matches = test_utils.GetOmniboxMatchesFor(self, search_string) self.assertTrue(matches) self.assertTrue([x for x in matches if x['type'] == 'search-suggest']) # Disable suggest-service. self.SetPrefs(pyauto.kSearchSuggestEnabled, False) self.assertFalse(self.GetPrefsInfo().Prefs(pyauto.kSearchSuggestEnabled)) matches = test_utils.GetOmniboxMatchesFor(self, search_string) self.assertTrue(matches) # Verify there are no suggest results. self.assertFalse([x for x in matches if x['type'] == 'search-suggest']) def testAutoCompleteForSearch(self): """Verify omnibox autocomplete for search.""" search_string = 'youtu' verify_string = 'youtube' matches = test_utils.GetOmniboxMatchesFor(self, search_string) # Retrieve last contents element. matches_description = matches[-1]['contents'].split() self.assertEqual(verify_string, matches_description[0]) def _GotContentHistory(self, search_text, url): """Check if omnibox returns a previously-visited page for given search text. Args: search_text: The string search text. url: The string URL to look for in the omnibox matches. Returns: True, if the omnibox returns the previously-visited page for the given search text, or False otherwise. """ # Omnibox doesn't change results if searching the same text repeatedly. # So setting '' in omnibox before the next repeated search. self.SetOmniboxText('') matches = test_utils.GetOmniboxMatchesFor(self, search_text) matches_description = [x for x in matches if x['destination_url'] == url] return 1 == len(matches_description) def testContentHistory(self): """Verify omnibox results when entering page content. Test verifies that visited page shows up in omnibox on entering page content. """ url = self.GetFileURLForPath( os.path.join(self.DataDir(), 'find_in_page', 'largepage.html')) self.NavigateToURL(url) self.assertTrue(self.WaitUntil( lambda: self._GotContentHistory('British throne', url))) def testOmniboxSearchHistory(self): """Verify page navigation/search from omnibox are added to the history.""" url = self.GetFileURLForDataPath('title2.html') self.NavigateToURL(url) self.AppendTab(pyauto.GURL('about:blank')) self.SetOmniboxText('java') self.WaitUntilOmniboxQueryDone() self.OmniboxAcceptInput() history = self.GetHistoryInfo().History() self.assertEqual(2, len(history)) self.assertEqual(url, history[1]['url']) self.assertEqual('java - Google Search', history[0]['title']) def _VerifyHasBookmarkResult(self, matches): """Verify that we have a bookmark result. Args: matches: A list of match items, as returned by test_utils.GetOmniboxMatchesFor(). """ matches_starred = [result for result in matches if result['starred']] self.assertTrue(matches_starred) self.assertEqual(1, len(matches_starred)) def _CheckBookmarkResultForVariousInputs(self, url, title, windex=0): """Check if we get the bookmark for complete and partial inputs. Args: url: A string URL. title: A string title for the given URL. windex: The window index to use. Defaults to 0 (first window). """ # Check if the complete URL would get the bookmark. url_matches = test_utils.GetOmniboxMatchesFor(self, url, windex=windex) self._VerifyHasBookmarkResult(url_matches) # Check if the complete title would get the bookmark. title_matches = test_utils.GetOmniboxMatchesFor(self, title, windex=windex) self._VerifyHasBookmarkResult(title_matches) # Check if the partial URL would get the bookmark. split_url = urlparse.urlsplit(url) partial_url = test_utils.GetOmniboxMatchesFor( self, split_url.scheme, windex=windex) self._VerifyHasBookmarkResult(partial_url) # Check if the partial title would get the bookmark. split_title = title.split() search_term = split_title[len(split_title) - 1] partial_title = test_utils.GetOmniboxMatchesFor( self, search_term, windex=windex) self._VerifyHasBookmarkResult(partial_title) def testBookmarkResultInNewTabAndWindow(self): """Verify omnibox finds bookmarks in search options of new tabs/windows.""" url = self.GetFileURLForDataPath('title2.html') self.NavigateToURL(url) title = 'This is Awesomeness' bookmarks = self.GetBookmarkModel() bar_id = bookmarks.BookmarkBar()['id'] self.AddBookmarkURL(bar_id, 0, title, url) bookmarks = self.GetBookmarkModel() nodes = bookmarks.FindByTitle(title) self.AppendTab(pyauto.GURL(url)) self._CheckBookmarkResultForVariousInputs(url, title) self.OpenNewBrowserWindow(True) self.assertEqual(2, self.GetBrowserWindowCount()) self.NavigateToURL(url, 1, 0) self._CheckBookmarkResultForVariousInputs(url, title, windex=1) self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW) self.assertEqual(3, self.GetBrowserWindowCount()) self.NavigateToURL(url, 2, 0) self._CheckBookmarkResultForVariousInputs(url, title, windex=2) def testAutoCompleteForNonAsciiSearch(self): """Verify can search/autocomplete with non-ASCII incomplete keywords.""" search_string = u'\u767e' verify_string = u'\u767e\u5ea6\u4e00\u4e0b' matches = test_utils.GetOmniboxMatchesFor(self, search_string) self.assertTrue(verify_string in matches[-1]['contents']) def _InstallAndVerifyApp(self, app_name): """Installs a sample packaged app and verifies the install is successful. Args: app_name: The name of the app to be installed. Returns: The string ID of the installed app. """ app_crx_file = os.path.abspath(os.path.join(self.DataDir(), 'pyauto_private', 'apps', app_name)) return self.InstallExtension(app_crx_file) def _VerifyOminiboxMatches(self, search_str, app_url, is_incognito): """Verify app matches in omnibox. Args: search_str: Search keyword to find app matches. app_url: Chrome app launch URL. is_incognito: A boolean indicating if omnibox matches are from an incognito window. """ def OminiboxMatchFound(): if is_incognito: matches = test_utils.GetOmniboxMatchesFor(self, search_str, windex=2) else: matches = test_utils.GetOmniboxMatchesFor(self, search_str) for x in matches: if x['destination_url'] == app_url: return True return False self.assertTrue(self.WaitUntil(OminiboxMatchFound), msg='Timed out waiting to verify omnibox matches.') def _VerifyAppSearchCurrentWindow(self, app_name, search_str, app_url): """Verify app can be searched and launched in omnibox of current window. Args: app_name: The name of an installed app. search_str: The search string to find the app from auto suggest. app_url: Chrome app launch URL. """ # Assume current window is at index 0. self._InstallAndVerifyApp(app_name) # Get app match in omnibox of the current window. self._VerifyOminiboxMatches(search_str, app_url, False) # Launch app from omnibox and verify it succeeds. self.OmniboxAcceptInput() # Blocks until the page loads. self.assertTrue(re.search(app_url, self.GetActiveTabURL().spec())) def _VerifyAppSearchIncognitoWindow(self, app_name, search_str, app_url): """Verify app can be searched and launched in omnibox of incognito window. Args: app_name: The name of installed app. search_str: The search string to find the app from auto suggest. app_url: Chrome app launch URL. """ # Assume current window is at index 0. self._InstallAndVerifyApp(app_name) # Get app matches in omnibox of the 3rd (incognito) window, assume # pre-exist 1st window. We have to launch 2 incognito windows here, # since there is an issue (crbug.com/99925) with app search in pyauto # launched 1st incognito window on Mac. # TODO(vivianz@): remove additional incognito window after issue 99925 is # fixed. self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW) self.WaitUntilOmniboxReadyHack(windex=1) self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW) self.WaitUntilOmniboxReadyHack(windex=2) # Get app match in omnibox of 3rd (incognito) window. self._VerifyOminiboxMatches(search_str, app_url, True) # Launch app from omnibox and verify it succeeds. self.OmniboxAcceptInput(windex=2) # Blocks until the page loads. self.assertTrue(re.search(app_url, self.GetActiveTabURL(2).spec())) def _VerifyAppSearchNewTab(self, app_name, search_str, app_url): """Verify app can be searched in new tab. Args: app_name: The name of installed app. search_str: The search string to find the app from auto suggest. app_url: Chrome app launch URL. """ self._InstallAndVerifyApp(app_name) # Get app matches in omnibox of the 2nd tab. self.AppendTab(pyauto.GURL()) self._VerifyOminiboxMatches(search_str, app_url, False) def testBasicAppSearch(self): """Verify that we can search for installed apps.""" app_name = 'countdown.crx' search_str = 'countdown' app_url = 'chrome-extension:' \ '//aeabikdlfbfeihglecobdkdflahfgcpd/launchLocalPath.html' self._VerifyAppSearchCurrentWindow(app_name, search_str, app_url) def testAppNameWithSpaceSearch(self): """Verify that we can search for apps with space in app name.""" app_name = 'cargo_bridge.crx' search_str = 'Cargo Bridge' app_url = 'http://webstore.limexgames.com/cargo_bridge' self._VerifyAppSearchCurrentWindow(app_name, search_str, app_url) def testAppNameWithNumberSearch(self): """Verify that we can search for apps with number in app name.""" app_name = '3d_stunt_pilot.crx' search_str = '3D Stunt Pilot' app_url = 'chrome-extension://cjhglkpjpcechghgbkdfoofgbphpgjde/index.html' self._VerifyAppSearchCurrentWindow(app_name, search_str, app_url) def testAppComboNameWithSpecialCharSearch(self): """Verify launch special character named app in regular window.""" app_name = 'atari_lunar_lander.crx' search_str = 'Atari - Lunar Lander' app_url = 'http://chrome.atari.com/lunarlander/' self._VerifyAppSearchCurrentWindow(app_name, search_str, app_url) def testAppSearchWithVeryLongAppName(self): """Verify that we can search app with very long app name.""" app_name = '20_thing_I_learn_from_browser_and_web.crx' search_str = '20 Things I Learned About Browsers & the Web' app_url = 'http://www.20thingsilearned.com/' self._VerifyAppSearchCurrentWindow(app_name, search_str, app_url) def testIncognitoAppNameWithSpaceSearch(self): """Verify search for apps with space in app name in incognito window.""" app_name = 'cargo_bridge.crx' search_str = 'Cargo Bridge' app_url = 'http://webstore.limexgames.com/cargo_bridge' self._VerifyAppSearchIncognitoWindow(app_name, search_str, app_url) def testIncognitoAppComboNameWithSpecialCharSearch(self): """Verify launch special character named app in incognito window.""" app_name = 'atari_lunar_lander.crx' search_str = 'Atari - Lunar Lander' app_url = 'http://chrome.atari.com/lunarlander/' self._VerifyAppSearchIncognitoWindow(app_name, search_str, app_url) def testIncognitoAppSearchWithVeryLongAppName(self): """Verify that we can launch app with very long app name.""" app_name = '20_thing_I_learn_from_browser_and_web.crx' search_str = '20 Things I Learned About Browsers & the Web' app_url = 'http://www.20thingsilearned.com/' self._VerifyAppSearchIncognitoWindow(app_name, search_str, app_url) def testRepeatedlyAppLaunchInTabs(self): """Verify that we can repeatedly launch app in tabs.""" app_name = '3d_stunt_pilot.crx' search_str = '3D Stunt Pilot' app_url = 'chrome-extension://cjhglkpjpcechghgbkdfoofgbphpgjde/index.html' self._VerifyAppSearchNewTab(app_name, search_str, app_url) # Launch app twice and verify it succeeds. self.OmniboxAcceptInput() self.assertTrue(re.search(app_url, self.GetActiveTabURL().spec())) self.AppendTab(pyauto.GURL()) self.SetOmniboxText(search_str) self.OmniboxAcceptInput() self.assertTrue(re.search(app_url, self.GetActiveTabURL().spec())) def testEndPartAppNameSearchInNewTab(self): """Verify that we can search app with partial app name (end part).""" app_name = 'countdown.crx' search_str = 'own' app_url = 'chrome-extension:' \ '//aeabikdlfbfeihglecobdkdflahfgcpd/launchLocalPath.html' self._VerifyAppSearchNewTab(app_name, search_str, app_url) def testBeginningPartAppNameSearchInNewTab(self): """Verify that we can search app with partial app name (beginning part).""" app_name = 'cargo_bridge.crx' search_str = 'Car' app_url = 'http://webstore.limexgames.com/cargo_bridge' self._VerifyAppSearchNewTab(app_name, search_str, app_url) if __name__ == '__main__': pyauto_functional.Main()