// 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. #include <string> #include "base/command_line.h" #include "base/json/json_reader.h" #include "base/scoped_ptr.h" #include "base/string_number_conversions.h" #include "base/values.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" #include "chrome/test/ui_test_utils.h" #include "content/browser/tab_contents/tab_contents.h" #include "googleurl/src/gurl.h" #include "net/base/mock_host_resolver.h" class ChromeAppAPITest : public ExtensionBrowserTest { private: virtual void SetUpCommandLine(CommandLine* command_line) { ExtensionBrowserTest::SetUpCommandLine(command_line); command_line->AppendSwitchASCII(switches::kAppsCheckoutURL, "http://checkout.com:"); } }; IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, IsInstalled) { std::string app_host("app.com"); std::string nonapp_host("nonapp.com"); host_resolver()->AddRule(app_host, "127.0.0.1"); host_resolver()->AddRule(nonapp_host, "127.0.0.1"); ASSERT_TRUE(test_server()->Start()); GURL test_file_url(test_server()->GetURL("extensions/test_file.html")); GURL::Replacements replace_host; replace_host.SetHostStr(app_host); GURL app_url(test_file_url.ReplaceComponents(replace_host)); replace_host.SetHostStr(nonapp_host); GURL non_app_url(test_file_url.ReplaceComponents(replace_host)); // Load an app which includes app.com in its extent. const Extension* extension = LoadExtension( test_data_dir_.AppendASCII("app_dot_com_app")); ASSERT_TRUE(extension); // Test that a non-app page has chrome.app.isInstalled = false. ui_test_utils::NavigateToURL(browser(), non_app_url); std::wstring get_app_is_installed = L"window.domAutomationController.send(" L" JSON.stringify(window.chrome.app.isInstalled));"; std::string result; ASSERT_TRUE( ui_test_utils::ExecuteJavaScriptAndExtractString( browser()->GetSelectedTabContents()->render_view_host(), L"", get_app_is_installed, &result)); EXPECT_EQ("false", result); // Test that a non-app page returns null for chrome.app.getDetails(). std::wstring get_app_details = L"window.domAutomationController.send(" L" JSON.stringify(window.chrome.app.getDetails()));"; ASSERT_TRUE( ui_test_utils::ExecuteJavaScriptAndExtractString( browser()->GetSelectedTabContents()->render_view_host(), L"", get_app_details, &result)); EXPECT_EQ("null", result); // Check that an app page has chrome.app.isInstalled = true. ui_test_utils::NavigateToURL(browser(), app_url); ASSERT_TRUE( ui_test_utils::ExecuteJavaScriptAndExtractString( browser()->GetSelectedTabContents()->render_view_host(), L"", get_app_is_installed, &result)); EXPECT_EQ("true", result); // Check that an app page returns the correct result for // chrome.app.getDetails(). ui_test_utils::NavigateToURL(browser(), app_url); ASSERT_TRUE( ui_test_utils::ExecuteJavaScriptAndExtractString( browser()->GetSelectedTabContents()->render_view_host(), L"", get_app_details, &result)); scoped_ptr<DictionaryValue> app_details( static_cast<DictionaryValue*>( base::JSONReader::Read(result, false /* allow trailing comma */))); // extension->manifest_value() does not contain the id. app_details->Remove("id", NULL); EXPECT_TRUE(app_details.get()); EXPECT_TRUE(app_details->Equals(extension->manifest_value())); // Test that trying to set window.chrome.app.isInstalled throws // an exception. ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( browser()->GetSelectedTabContents()->render_view_host(), L"", L"window.domAutomationController.send(" L" function() {" L" try {" L" window.chrome.app.isInstalled = false;" L" return 'BAD: Should have thrown by now...';" L" } catch (e) {" L" return 'GOOD: Saw expected error.';" L" }" L" }()" L");", &result)); EXPECT_EQ("GOOD: Saw expected error.", result); } IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, GetDetailsForFrame) { std::string app_host("app.com"); std::string nonapp_host("nonapp.com"); std::string checkout_host("checkout.com"); host_resolver()->AddRule(app_host, "127.0.0.1"); host_resolver()->AddRule(nonapp_host, "127.0.0.1"); host_resolver()->AddRule(checkout_host, "127.0.0.1"); ASSERT_TRUE(test_server()->Start()); GURL test_file_url(test_server()->GetURL( "files/extensions/get_app_details_for_frame.html")); GURL::Replacements replace_host; replace_host.SetHostStr(checkout_host); GURL checkout_url(test_file_url.ReplaceComponents(replace_host)); replace_host.SetHostStr(app_host); GURL app_url(test_file_url.ReplaceComponents(replace_host)); // Load an app which includes app.com in its extent. const Extension* extension = LoadExtension( test_data_dir_.AppendASCII("app_dot_com_app")); ASSERT_TRUE(extension); // Test that normal pages (even apps) cannot use getDetailsForFrame(). ui_test_utils::NavigateToURL(browser(), app_url); std::wstring test_unsuccessful_access = L"window.domAutomationController.send(window.testUnsuccessfulAccess())"; bool result = false; ASSERT_TRUE( ui_test_utils::ExecuteJavaScriptAndExtractBool( browser()->GetSelectedTabContents()->render_view_host(), L"", test_unsuccessful_access, &result)); EXPECT_TRUE(result); // Test that checkout can use getDetailsForFrame() and that it works // correctly. ui_test_utils::NavigateToURL(browser(), checkout_url); std::wstring get_details_for_frame = L"window.domAutomationController.send(" L" JSON.stringify(chrome.app.getDetailsForFrame(frames[0])))"; std::string json; ASSERT_TRUE( ui_test_utils::ExecuteJavaScriptAndExtractString( browser()->GetSelectedTabContents()->render_view_host(), L"", get_details_for_frame, &json)); scoped_ptr<DictionaryValue> app_details( static_cast<DictionaryValue*>( base::JSONReader::Read(json, false /* allow trailing comma */))); // extension->manifest_value() does not contain the id. app_details->Remove("id", NULL); EXPECT_TRUE(app_details.get()); EXPECT_TRUE(app_details->Equals(extension->manifest_value())); }