OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 "ash/shell.h" | |
6 #include "ash/system/cast/tray_cast.h" | |
7 #include "ash/system/tray/system_tray.h" | |
8 #include "ash/system/tray/system_tray_delegate.h" | |
9 #include "ash/system/tray/system_tray_item.h" | |
10 #include "ash/test/tray_cast_test_api.h" | |
11 #include "chrome/browser/extensions/extension_browsertest.h" | |
12 #include "chrome/browser/profiles/profile_manager.h" | |
13 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
14 #include "content/public/browser/render_view_host.h" | |
15 #include "content/public/test/test_utils.h" | |
16 #include "extensions/browser/process_manager.h" | |
17 | |
18 namespace { | |
19 | |
20 // Execute JavaScript within the context of the extension. Returns the result | |
21 // of the execution. | |
22 scoped_ptr<base::Value> ExecuteJavaScript( | |
23 const extensions::Extension* extension, | |
24 const std::string& javascript) { | |
25 Profile* profile = ProfileManager::GetActiveUserProfile(); | |
26 auto pm = extensions::ProcessManager::Get(profile); | |
27 content::RenderViewHost* host = | |
28 pm->GetBackgroundHostForExtension(extension->id())->render_view_host(); | |
29 return content::ExecuteScriptAndGetValue(host->GetMainFrame(), javascript); | |
30 } | |
31 | |
32 // Returns the current value within a global JavaScript variable. | |
33 scoped_ptr<base::Value> GetJavaScriptVariable( | |
34 const extensions::Extension* extension, | |
35 const std::string& variable) { | |
36 return ExecuteJavaScript(extension, | |
37 "(function() { return " + variable + "; })()"); | |
38 } | |
39 | |
40 std::string GetJavaScriptStringVariable(const extensions::Extension* extension, | |
41 const std::string& variable) { | |
42 scoped_ptr<base::Value> value = GetJavaScriptVariable(extension, variable); | |
43 std::string result; | |
44 DCHECK(value->GetAsString(&result)); | |
45 return result; | |
46 } | |
47 | |
48 bool GetJavaScriptBooleanVariable(const extensions::Extension* extension, | |
49 const std::string& variable) { | |
50 scoped_ptr<base::Value> value = GetJavaScriptVariable(extension, variable); | |
51 bool result; | |
52 DCHECK(value->GetAsBoolean(&result)); | |
53 return result; | |
54 } | |
55 | |
56 // Ensures that all pending JavaScript execution callbacks are invoked. | |
57 void ExecutePendingJavaScript(const extensions::Extension* extension) { | |
58 ExecuteJavaScript(extension, std::string()); | |
59 } | |
60 | |
61 // Invokes tray->StartCast(id) and returns true if launchDesktopMirroring was | |
62 // called with the same id. This automatically creates/destroys the detail view | |
63 // and notifies the tray that Chrome has begun casting. | |
64 bool StartCastWithVerification(const extensions::Extension* extension, | |
65 ash::TrayCast* tray, | |
66 const std::string& receiver_id) { | |
67 ash::SystemTrayItem* system_tray_item = tray; | |
68 ash::TrayCastTestAPI test_tray(tray); | |
69 | |
70 // We will simulate a button click in the detail view to begin the cast, so we | |
71 // need to make a detail view available. | |
72 system_tray_item->CreateDetailedView(ash::user::LoginStatus::LOGGED_IN_USER); | |
73 | |
74 // Clear out any old state and execute any pending JS calls created from the | |
75 // CreateDetailedView call. | |
76 ExecuteJavaScript(extension, "launchDesktopMirroringReceiverId = ''"); | |
77 | |
78 // Tell the tray item that Chrome has started casting. | |
79 test_tray.StartCast(receiver_id); | |
80 test_tray.OnCastingSessionStartedOrStopped(true); | |
81 | |
82 system_tray_item->DestroyDetailedView(); | |
83 | |
84 return receiver_id == GetJavaScriptStringVariable( | |
85 extension, "launchDesktopMirroringReceiverId"); | |
86 } | |
87 | |
88 // Invokes tray->StopCast() and returns true if stopMirroring('user-stop') | |
89 // was called in the extension. | |
90 bool StopCastWithVerification(const extensions::Extension* extension, | |
91 ash::TrayCastTestAPI* tray) { | |
92 // Clear out any old state so we can be sure that we set the value here. | |
93 ExecuteJavaScript(extension, "stopMirroringCalled = false"); | |
94 | |
95 // Stop casting. | |
96 tray->StopCast(); | |
97 tray->OnCastingSessionStartedOrStopped(false); | |
98 | |
99 return GetJavaScriptBooleanVariable(extension, "stopMirroringCalled"); | |
100 } | |
101 | |
102 // Returns the cast tray. The tray initializer may have launched some | |
103 // JavaScript callbacks which have not finished executing. | |
104 ash::TrayCast* GetTrayCast(const extensions::Extension* extension) { | |
105 ash::SystemTray* tray = ash::Shell::GetInstance()->GetPrimarySystemTray(); | |
106 | |
107 // Make sure we actually popup the tray, otherwise the TrayCast instance will | |
108 // not be created. | |
109 tray->ShowDefaultView(ash::BubbleCreationType::BUBBLE_CREATE_NEW); | |
110 | |
111 // Creating the tray causes some JavaScript to be executed. Let's try to make | |
112 // sure it is completed. | |
113 if (extension) | |
114 ExecutePendingJavaScript(extension); | |
115 | |
116 return tray->GetTrayCastForTesting(); | |
117 } | |
118 | |
119 class SystemTrayTrayCastChromeOSTest : public ExtensionBrowserTest { | |
120 protected: | |
121 SystemTrayTrayCastChromeOSTest() : ExtensionBrowserTest() {} | |
122 ~SystemTrayTrayCastChromeOSTest() override {} | |
123 | |
124 const extensions::Extension* LoadCastTestExtension() { | |
125 return LoadExtension(test_data_dir_.AppendASCII("tray_cast")); | |
126 } | |
127 | |
128 private: | |
129 DISALLOW_COPY_AND_ASSIGN(SystemTrayTrayCastChromeOSTest); | |
130 }; | |
131 | |
132 } // namespace | |
133 | |
134 namespace chromeos { | |
135 | |
136 // A simple sanity check to make sure that the cast config delegate actually | |
137 // recognizes the cast extension. | |
138 IN_PROC_BROWSER_TEST_F(SystemTrayTrayCastChromeOSTest, | |
139 CastTraySanityCheckTestExtensionGetsRecognized) { | |
140 ash::CastConfigDelegate* cast_config_delegate = ash::Shell::GetInstance() | |
141 ->system_tray_delegate() | |
142 ->GetCastConfigDelegate(); | |
143 | |
144 EXPECT_FALSE(cast_config_delegate->HasCastExtension()); | |
145 const extensions::Extension* extension = LoadCastTestExtension(); | |
146 EXPECT_TRUE(cast_config_delegate->HasCastExtension()); | |
147 UninstallExtension(extension->id()); | |
148 } | |
149 | |
150 // Verifies that the cast tray is hidden when there is no extension installed. | |
151 IN_PROC_BROWSER_TEST_F(SystemTrayTrayCastChromeOSTest, | |
152 CastTrayIsHiddenWhenThereIsNoExtension) { | |
153 ash::TrayCastTestAPI tray(GetTrayCast(nullptr)); | |
154 EXPECT_TRUE(tray.IsTrayInitialized()); | |
155 EXPECT_FALSE(tray.IsTrayVisible()); | |
156 } | |
157 | |
158 // Verifies that the cast tray is hidden if there are no available receivers, | |
159 // even if there is an extension installed. | |
160 IN_PROC_BROWSER_TEST_F(SystemTrayTrayCastChromeOSTest, | |
161 CastTrayIsHiddenWhenThereIsAnExtensionButNoReceivers) { | |
162 const extensions::Extension* extension = LoadCastTestExtension(); | |
163 | |
164 ash::TrayCastTestAPI tray(GetTrayCast(extension)); | |
165 EXPECT_TRUE(tray.IsTrayInitialized()); | |
166 EXPECT_FALSE(tray.IsTrayVisible()); | |
167 | |
168 UninstallExtension(extension->id()); | |
169 } | |
170 | |
171 // Verifies that the cast tray is displayed when there are receivers available. | |
172 IN_PROC_BROWSER_TEST_F(SystemTrayTrayCastChromeOSTest, | |
173 CastTrayIsDisplayedWhenThereIsAnExtensionWithReceivers) { | |
174 const extensions::Extension* extension = LoadCastTestExtension(); | |
175 ExecuteJavaScript(extension, "addReceiver('test_id', 'name')"); | |
176 | |
177 ash::TrayCastTestAPI tray(GetTrayCast(extension)); | |
178 | |
179 EXPECT_TRUE(tray.IsTrayInitialized()); | |
180 EXPECT_TRUE(tray.IsTrayVisible()); | |
181 | |
182 UninstallExtension(extension->id()); | |
183 } | |
184 | |
185 // Verifies that we can cast to a specific receiver, stop casting, and then cast | |
186 // to another receiver when there is more than one receiver | |
187 IN_PROC_BROWSER_TEST_F(SystemTrayTrayCastChromeOSTest, | |
188 CastTrayMultipleReceivers) { | |
189 const extensions::Extension* extension = LoadCastTestExtension(); | |
190 ExecuteJavaScript(extension, "addReceiver('test_id_1', 'name')"); | |
191 ExecuteJavaScript(extension, "addReceiver('not_used_0', 'name1')"); | |
192 ExecuteJavaScript(extension, "addReceiver('test_id_0', 'name')"); | |
193 ExecuteJavaScript(extension, "addReceiver('not_used_1', 'name2')"); | |
194 | |
195 ash::TrayCast* tray = GetTrayCast(extension); | |
196 ash::TrayCastTestAPI test_tray(tray); | |
197 EXPECT_TRUE(StartCastWithVerification(extension, tray, "test_id_0")); | |
198 | |
199 EXPECT_TRUE(test_tray.IsTrayCastViewVisible()); | |
200 EXPECT_TRUE(StopCastWithVerification(extension, &test_tray)); | |
201 EXPECT_TRUE(test_tray.IsTraySelectViewVisible()); | |
202 | |
203 EXPECT_TRUE(StartCastWithVerification(extension, tray, "test_id_1")); | |
204 EXPECT_TRUE(test_tray.IsTrayCastViewVisible()); | |
205 EXPECT_TRUE(StopCastWithVerification(extension, &test_tray)); | |
206 EXPECT_TRUE(test_tray.IsTraySelectViewVisible()); | |
207 | |
208 UninstallExtension(extension->id()); | |
209 } | |
210 | |
211 // Verifies the stop cast button invokes the JavaScript function | |
212 // "stopMirroring('user-stop')". | |
213 IN_PROC_BROWSER_TEST_F(SystemTrayTrayCastChromeOSTest, | |
214 CastTrayStopButtonStopsCast) { | |
215 // Add a receiver that is casting. | |
216 const extensions::Extension* extension = LoadCastTestExtension(); | |
217 ExecuteJavaScript(extension, "addReceiver('test_id', 'name', 'title', 1)"); | |
218 | |
219 ash::TrayCastTestAPI test_tray(GetTrayCast(extension)); | |
220 test_tray.OnCastingSessionStartedOrStopped(true); | |
221 ExecutePendingJavaScript(extension); | |
222 EXPECT_TRUE(test_tray.IsTrayCastViewVisible()); | |
223 | |
224 // Stop the cast using the UI. | |
225 EXPECT_TRUE(StopCastWithVerification(extension, &test_tray)); | |
226 EXPECT_TRUE(test_tray.IsTraySelectViewVisible()); | |
227 | |
228 UninstallExtension(extension->id()); | |
229 } | |
230 | |
231 // Verifies that the start cast button invokes "launchDesktopMirroring(...)". | |
232 IN_PROC_BROWSER_TEST_F(SystemTrayTrayCastChromeOSTest, | |
233 CastTrayStartButtonStartsCast) { | |
234 const extensions::Extension* extension = LoadCastTestExtension(); | |
235 ExecuteJavaScript(extension, "addReceiver('test_id', 'name')"); | |
236 ash::TrayCast* tray = GetTrayCast(extension); | |
237 EXPECT_TRUE(StartCastWithVerification(extension, tray, "test_id")); | |
238 UninstallExtension(extension->id()); | |
239 } | |
240 | |
241 // Verifies that the CastConfigDelegate opens up a tab called "options.html". | |
242 IN_PROC_BROWSER_TEST_F(SystemTrayTrayCastChromeOSTest, CastTrayOpenOptions) { | |
243 const extensions::Extension* extension = LoadCastTestExtension(); | |
244 | |
245 ash::CastConfigDelegate* cast_config_delegate = ash::Shell::GetInstance() | |
246 ->system_tray_delegate() | |
247 ->GetCastConfigDelegate(); | |
248 cast_config_delegate->LaunchCastOptions(); | |
249 | |
250 const GURL url = | |
251 browser()->tab_strip_model()->GetActiveWebContents()->GetURL(); | |
252 EXPECT_TRUE(base::StringPiece(url.GetContent()).ends_with("options.html")); | |
253 | |
254 UninstallExtension(extension->id()); | |
255 } | |
256 | |
257 } // namespace chromeos | |
OLD | NEW |