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/command_line.h"
8#include "base/json/json_reader.h"
9#include "base/scoped_ptr.h"
10#include "base/string_number_conversions.h"
11#include "base/values.h"
12#include "chrome/browser/extensions/extension_browsertest.h"
13#include "chrome/browser/ui/browser.h"
14#include "chrome/common/chrome_switches.h"
15#include "chrome/common/extensions/extension.h"
16#include "chrome/test/ui_test_utils.h"
17#include "content/browser/tab_contents/tab_contents.h"
18#include "googleurl/src/gurl.h"
19#include "net/base/mock_host_resolver.h"
20
21class ChromeAppAPITest : public ExtensionBrowserTest {
22 private:
23  virtual void SetUpCommandLine(CommandLine* command_line) {
24    ExtensionBrowserTest::SetUpCommandLine(command_line);
25    command_line->AppendSwitchASCII(switches::kAppsCheckoutURL,
26                                    "http://checkout.com:");
27  }
28};
29
30IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, IsInstalled) {
31  std::string app_host("app.com");
32  std::string nonapp_host("nonapp.com");
33
34  host_resolver()->AddRule(app_host, "127.0.0.1");
35  host_resolver()->AddRule(nonapp_host, "127.0.0.1");
36  ASSERT_TRUE(test_server()->Start());
37
38  GURL test_file_url(test_server()->GetURL("extensions/test_file.html"));
39  GURL::Replacements replace_host;
40
41  replace_host.SetHostStr(app_host);
42  GURL app_url(test_file_url.ReplaceComponents(replace_host));
43
44  replace_host.SetHostStr(nonapp_host);
45  GURL non_app_url(test_file_url.ReplaceComponents(replace_host));
46
47
48  // Load an app which includes app.com in its extent.
49  const Extension* extension = LoadExtension(
50      test_data_dir_.AppendASCII("app_dot_com_app"));
51  ASSERT_TRUE(extension);
52
53
54  // Test that a non-app page has chrome.app.isInstalled = false.
55  ui_test_utils::NavigateToURL(browser(), non_app_url);
56  std::wstring get_app_is_installed =
57      L"window.domAutomationController.send("
58      L"    JSON.stringify(window.chrome.app.isInstalled));";
59  std::string result;
60  ASSERT_TRUE(
61      ui_test_utils::ExecuteJavaScriptAndExtractString(
62          browser()->GetSelectedTabContents()->render_view_host(),
63          L"", get_app_is_installed, &result));
64  EXPECT_EQ("false", result);
65
66  // Test that a non-app page returns null for chrome.app.getDetails().
67  std::wstring get_app_details =
68      L"window.domAutomationController.send("
69      L"    JSON.stringify(window.chrome.app.getDetails()));";
70  ASSERT_TRUE(
71      ui_test_utils::ExecuteJavaScriptAndExtractString(
72          browser()->GetSelectedTabContents()->render_view_host(),
73          L"", get_app_details, &result));
74  EXPECT_EQ("null", result);
75
76  // Check that an app page has chrome.app.isInstalled = true.
77  ui_test_utils::NavigateToURL(browser(), app_url);
78  ASSERT_TRUE(
79      ui_test_utils::ExecuteJavaScriptAndExtractString(
80          browser()->GetSelectedTabContents()->render_view_host(),
81          L"", get_app_is_installed, &result));
82  EXPECT_EQ("true", result);
83
84  // Check that an app page returns the correct result for
85  // chrome.app.getDetails().
86  ui_test_utils::NavigateToURL(browser(), app_url);
87  ASSERT_TRUE(
88      ui_test_utils::ExecuteJavaScriptAndExtractString(
89          browser()->GetSelectedTabContents()->render_view_host(),
90          L"", get_app_details, &result));
91  scoped_ptr<DictionaryValue> app_details(
92      static_cast<DictionaryValue*>(
93          base::JSONReader::Read(result, false /* allow trailing comma */)));
94  // extension->manifest_value() does not contain the id.
95  app_details->Remove("id", NULL);
96  EXPECT_TRUE(app_details.get());
97  EXPECT_TRUE(app_details->Equals(extension->manifest_value()));
98
99
100  // Test that trying to set window.chrome.app.isInstalled throws
101  // an exception.
102  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
103          browser()->GetSelectedTabContents()->render_view_host(),
104          L"",
105          L"window.domAutomationController.send("
106          L"    function() {"
107          L"      try {"
108          L"        window.chrome.app.isInstalled = false;"
109          L"        return 'BAD: Should have thrown by now...';"
110          L"      } catch (e) {"
111          L"        return 'GOOD: Saw expected error.';"
112          L"      }"
113          L"    }()"
114          L");",
115          &result));
116  EXPECT_EQ("GOOD: Saw expected error.", result);
117}
118
119IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, GetDetailsForFrame) {
120  std::string app_host("app.com");
121  std::string nonapp_host("nonapp.com");
122  std::string checkout_host("checkout.com");
123
124  host_resolver()->AddRule(app_host, "127.0.0.1");
125  host_resolver()->AddRule(nonapp_host, "127.0.0.1");
126  host_resolver()->AddRule(checkout_host, "127.0.0.1");
127  ASSERT_TRUE(test_server()->Start());
128
129  GURL test_file_url(test_server()->GetURL(
130      "files/extensions/get_app_details_for_frame.html"));
131  GURL::Replacements replace_host;
132
133  replace_host.SetHostStr(checkout_host);
134  GURL checkout_url(test_file_url.ReplaceComponents(replace_host));
135
136  replace_host.SetHostStr(app_host);
137  GURL app_url(test_file_url.ReplaceComponents(replace_host));
138
139  // Load an app which includes app.com in its extent.
140  const Extension* extension = LoadExtension(
141      test_data_dir_.AppendASCII("app_dot_com_app"));
142  ASSERT_TRUE(extension);
143
144  // Test that normal pages (even apps) cannot use getDetailsForFrame().
145  ui_test_utils::NavigateToURL(browser(), app_url);
146  std::wstring test_unsuccessful_access =
147      L"window.domAutomationController.send(window.testUnsuccessfulAccess())";
148  bool result = false;
149  ASSERT_TRUE(
150      ui_test_utils::ExecuteJavaScriptAndExtractBool(
151          browser()->GetSelectedTabContents()->render_view_host(),
152          L"", test_unsuccessful_access, &result));
153  EXPECT_TRUE(result);
154
155  // Test that checkout can use getDetailsForFrame() and that it works
156  // correctly.
157  ui_test_utils::NavigateToURL(browser(), checkout_url);
158  std::wstring get_details_for_frame =
159      L"window.domAutomationController.send("
160      L"    JSON.stringify(chrome.app.getDetailsForFrame(frames[0])))";
161  std::string json;
162  ASSERT_TRUE(
163      ui_test_utils::ExecuteJavaScriptAndExtractString(
164          browser()->GetSelectedTabContents()->render_view_host(),
165          L"", get_details_for_frame, &json));
166
167  scoped_ptr<DictionaryValue> app_details(
168      static_cast<DictionaryValue*>(
169          base::JSONReader::Read(json, false /* allow trailing comma */)));
170  // extension->manifest_value() does not contain the id.
171  app_details->Remove("id", NULL);
172  EXPECT_TRUE(app_details.get());
173  EXPECT_TRUE(app_details->Equals(extension->manifest_value()));
174}
175