extension_apitest.h revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_APITEST_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_BROWSER_EXTENSIONS_EXTENSION_APITEST_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <deque> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_browsertest.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_registrar.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace base { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FilePath; 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Extension; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The general flow of these API tests should work like this: 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (1) Setup initial browser state (e.g. create some bookmarks for the 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bookmark test) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (2) Call ASSERT_TRUE(RunExtensionTest(name)); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (3) In your extension code, run your test and call chrome.test.pass or 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// chrome.test.fail 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (4) Verify expected browser state. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(erikkay): There should also be a way to drive events in these tests. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionApiTest : public ExtensionBrowserTest { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Flags used to configure how the tests are run. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(aa): Many of these are dupes of ExtensionBrowserTest::Flags. Combine 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // somehow? 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum Flags { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFlagNone = 0, 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allow the extension to run in incognito mode. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFlagEnableIncognito = 1 << 0, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Launch the test page in an incognito window. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFlagUseIncognito = 1 << 1, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allow file access for the extension. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFlagEnableFileAccess = 1 << 2, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Loads the extension with location COMPONENT. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFlagLoadAsComponent = 1 << 3, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Launch the extension as a platform app. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFlagLaunchPlatformApp = 1 << 4, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't fail when the loaded manifest has warnings. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFlagIgnoreManifestWarnings = 1 << 5, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allow manifest versions older that Extension::kModernManifestVersion. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Used to test old manifest features. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFlagAllowOldManifestVersions = 1 << 6, 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionApiTest(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ExtensionApiTest(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Helper class that observes tests failing or passing. Observation starts 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when the class is constructed. Get the next result by calling 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GetNextResult() and message() if GetNextResult() return false. If there 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are no results, this method will pump the UI message loop until one is 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // received. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class ResultCatcher : public content::NotificationObserver { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResultCatcher(); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ResultCatcher(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pumps the UI loop until a notification is received that an API test 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // succeeded or failed. Returns true if the test succeeded, false otherwise. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool GetNextResult(); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RestrictToProfile(Profile* profile) { profile_restriction_ = profile; } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& message() { return message_; } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Observe(int type, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) OVERRIDE; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationRegistrar registrar_; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A sequential list of pass/fail notifications from the test extension(s). 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::deque<bool> results_; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If it failed, what was the error message? 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::deque<std::string> messages_; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string message_; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If non-NULL, we will listen to events from this profile only. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile_restriction_; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // True if we're in a nested message loop waiting for results from 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the extension. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool waiting_; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUpInProcessBrowserTestFixture() OVERRIDE; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void TearDownInProcessBrowserTestFixture() OVERRIDE; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Load |extension_name| and wait for pass / fail notification. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |extension_name| is a directory in "test/data/extensions/api_test". 11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool RunExtensionTest(const std::string& extension_name); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Same as RunExtensionTest, but enables the extension for incognito mode. 11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool RunExtensionTestIncognito(const std::string& extension_name); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Same as RunExtensionTest, but ignores any warnings in the manifest. 11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool RunExtensionTestIgnoreManifestWarnings( 11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& extension_name); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Same as RunExtensionTest, allow old manifest ersions. 12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool RunExtensionTestAllowOldManifestVersion( 12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& extension_name); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Same as RunExtensionTest, but loads extension as component. 12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool RunComponentExtensionTest(const std::string& extension_name); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Same as RunExtensionTest, but disables file access. 12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool RunExtensionTestNoFileAccess(const std::string& extension_name); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Same as RunExtensionTestIncognito, but disables file access. 13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool RunExtensionTestIncognitoNoFileAccess(const std::string& extension_name); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If not empty, Load |extension_name|, load |page_url| and wait for pass / 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fail notification from the extension API on the page. Note that if 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |page_url| is not a valid url, it will be treated as a resource within 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the extension. |extension_name| is a directory in 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "test/data/extensions/api_test". 13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool RunExtensionSubtest(const std::string& extension_name, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& page_url); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Same as RunExtensionSubtest, except run with the specific |flags| 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (as defined in the Flags enum). 14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool RunExtensionSubtest(const std::string& extension_name, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& page_url, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Load |page_url| and wait for pass / fail notification from the extension 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // API on the page. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool RunPageTest(const std::string& page_url); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool RunPageTest(const std::string& page_url, int flags); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Similar to RunExtensionTest, except used for running tests in platform app 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shell windows. 15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool RunPlatformAppTest(const std::string& extension_name); 15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 1577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Similar to RunPlatformAppTest, except sets an additional string argument 1587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // |customArg| to the test config object. 1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool RunPlatformAppTestWithArg( 16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& extension_name, const char* custom_arg); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start the test server, and store details of its state. Those details 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be available to javascript tests using chrome.test.getConfig(). 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool StartEmbeddedTestServer(); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start the test WebSocket server, and store details of its state. Those 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // details will be available to javascript tests using 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // chrome.test.getConfig(). 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool StartWebSocketServer(const base::FilePath& root_directory); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test that exactly one extension loaded. If so, return a pointer to 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the extension. If not, return NULL and set message_. 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const extensions::Extension* GetSingleLoadedExtension(); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All extensions tested by ExtensionApiTest are in the "api_test" dir. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If it failed, what was the error message? 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string message_; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool RunExtensionTestImpl(const std::string& extension_name, 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& test_page, 1847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const char* custom_arg, 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hold details of the test, set in C++, which can be accessed by 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // javascript using chrome.test.getConfig(). 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<DictionaryValue> test_config_; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hold the test WebSocket server. 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<net::SpawnedTestServer> websocket_server_; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_APITEST_H_ 196