• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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 <queue>
6 
7 #include "base/command_line.h"
8 #include "base/path_service.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h"
11 #include "chrome/browser/extensions/extension_apitest.h"
12 #include "chrome/browser/media/fake_desktop_media_list.h"
13 #include "chrome/browser/ui/tabs/tab_strip_model.h"
14 #include "chrome/common/chrome_paths.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "chrome/test/base/ui_test_utils.h"
17 #include "content/public/test/browser_test_utils.h"
18 #include "net/dns/mock_host_resolver.h"
19 #include "net/test/embedded_test_server/embedded_test_server.h"
20 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h"
21 
22 namespace extensions {
23 
24 namespace {
25 
26 struct TestFlags {
27   bool expect_screens;
28   bool expect_windows;
29   content::DesktopMediaID selected_source;
30   bool cancelled;
31 
32   // Following flags are set by FakeDesktopMediaPicker when it's created and
33   // deleted.
34   bool picker_created;
35   bool picker_deleted;
36 };
37 
38 class FakeDesktopMediaPicker : public DesktopMediaPicker {
39  public:
FakeDesktopMediaPicker(TestFlags * expectation)40   explicit FakeDesktopMediaPicker(TestFlags* expectation)
41       : expectation_(expectation),
42         weak_factory_(this) {
43     expectation_->picker_created = true;
44   }
~FakeDesktopMediaPicker()45   virtual ~FakeDesktopMediaPicker() {
46     expectation_->picker_deleted = true;
47   }
48 
49   // DesktopMediaPicker interface.
Show(content::WebContents * web_contents,gfx::NativeWindow context,gfx::NativeWindow parent,const base::string16 & app_name,const base::string16 & target_name,scoped_ptr<DesktopMediaList> model,const DoneCallback & done_callback)50   virtual void Show(content::WebContents* web_contents,
51                     gfx::NativeWindow context,
52                     gfx::NativeWindow parent,
53                     const base::string16& app_name,
54                     const base::string16& target_name,
55                     scoped_ptr<DesktopMediaList> model,
56                     const DoneCallback& done_callback) OVERRIDE {
57     if (!expectation_->cancelled) {
58       // Post a task to call the callback asynchronously.
59       base::ThreadTaskRunnerHandle::Get()->PostTask(
60           FROM_HERE,
61           base::Bind(&FakeDesktopMediaPicker::CallCallback,
62                      weak_factory_.GetWeakPtr(), done_callback));
63     } else {
64       // If we expect the dialog to be cancelled then store the callback to
65       // retain reference to the callback handler.
66       done_callback_ = done_callback;
67     }
68   }
69 
70  private:
CallCallback(DoneCallback done_callback)71   void CallCallback(DoneCallback done_callback) {
72     done_callback.Run(expectation_->selected_source);
73   }
74 
75   TestFlags* expectation_;
76   DoneCallback done_callback_;
77 
78   base::WeakPtrFactory<FakeDesktopMediaPicker> weak_factory_;
79 
80   DISALLOW_COPY_AND_ASSIGN(FakeDesktopMediaPicker);
81 };
82 
83 class FakeDesktopMediaPickerFactory :
84     public DesktopCaptureChooseDesktopMediaFunction::PickerFactory {
85  public:
FakeDesktopMediaPickerFactory()86   FakeDesktopMediaPickerFactory() {}
~FakeDesktopMediaPickerFactory()87   virtual ~FakeDesktopMediaPickerFactory() {}
88 
SetTestFlags(TestFlags * test_flags,int tests_count)89   void SetTestFlags(TestFlags* test_flags, int tests_count) {
90     test_flags_ = test_flags;
91     tests_count_ = tests_count;
92     current_test_ = 0;
93   }
94 
95   // DesktopCaptureChooseDesktopMediaFunction::PickerFactory interface.
CreateModel(bool show_screens,bool show_windows)96   virtual scoped_ptr<DesktopMediaList> CreateModel(
97       bool show_screens,
98       bool show_windows) OVERRIDE {
99     EXPECT_LE(current_test_, tests_count_);
100     if (current_test_ >= tests_count_)
101       return scoped_ptr<DesktopMediaList>();
102     EXPECT_EQ(test_flags_[current_test_].expect_screens, show_screens);
103     EXPECT_EQ(test_flags_[current_test_].expect_windows, show_windows);
104     return scoped_ptr<DesktopMediaList>(new FakeDesktopMediaList());
105   }
106 
CreatePicker()107   virtual scoped_ptr<DesktopMediaPicker> CreatePicker() OVERRIDE {
108     EXPECT_LE(current_test_, tests_count_);
109     if (current_test_ >= tests_count_)
110       return scoped_ptr<DesktopMediaPicker>();
111     ++current_test_;
112     return scoped_ptr<DesktopMediaPicker>(
113         new FakeDesktopMediaPicker(test_flags_ + current_test_ - 1));
114   }
115 
116  private:
117   TestFlags* test_flags_;
118   int tests_count_;
119   int current_test_;
120 
121   DISALLOW_COPY_AND_ASSIGN(FakeDesktopMediaPickerFactory);
122 };
123 
124 class DesktopCaptureApiTest : public ExtensionApiTest {
125  public:
DesktopCaptureApiTest()126   DesktopCaptureApiTest() {
127     DesktopCaptureChooseDesktopMediaFunction::
128         SetPickerFactoryForTests(&picker_factory_);
129   }
~DesktopCaptureApiTest()130   virtual ~DesktopCaptureApiTest() {
131     DesktopCaptureChooseDesktopMediaFunction::
132         SetPickerFactoryForTests(NULL);
133   }
134 
135  protected:
GetURLForPath(const std::string & host,const std::string & path)136   GURL GetURLForPath(const std::string& host, const std::string& path) {
137     std::string port = base::IntToString(embedded_test_server()->port());
138     GURL::Replacements replacements;
139     replacements.SetHostStr(host);
140     replacements.SetPortStr(port);
141     return embedded_test_server()->GetURL(path).ReplaceComponents(replacements);
142   }
143 
144   FakeDesktopMediaPickerFactory picker_factory_;
145 };
146 
147 }  // namespace
148 
149 // Flaky on Windows: http://crbug.com/301887
150 #if defined(OS_WIN)
151 #define MAYBE_ChooseDesktopMedia DISABLED_ChooseDesktopMedia
152 #else
153 #define MAYBE_ChooseDesktopMedia ChooseDesktopMedia
154 #endif
IN_PROC_BROWSER_TEST_F(DesktopCaptureApiTest,MAYBE_ChooseDesktopMedia)155 IN_PROC_BROWSER_TEST_F(DesktopCaptureApiTest, MAYBE_ChooseDesktopMedia) {
156   // Each element in the following array corresponds to one test in
157   // chrome/test/data/extensions/api_test/desktop_capture/test.js .
158   TestFlags test_flags[] = {
159     // pickerUiCanceled()
160     { true, true,
161       content::DesktopMediaID() },
162     // chooseMedia()
163     { true, true,
164       content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0) },
165     // screensOnly()
166     { true, false,
167       content::DesktopMediaID() },
168     // WindowsOnly()
169     { false, true,
170       content::DesktopMediaID() },
171     // chooseMediaAndGetStream()
172     { true, true,
173       content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
174                               webrtc::kFullDesktopScreenId) },
175     // chooseMediaAndTryGetStreamWithInvalidId()
176     { true, true,
177       content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
178                               webrtc::kFullDesktopScreenId) },
179     // cancelDialog()
180     { true, true,
181       content::DesktopMediaID(), true },
182   };
183   picker_factory_.SetTestFlags(test_flags, arraysize(test_flags));
184   ASSERT_TRUE(RunExtensionTest("desktop_capture")) << message_;
185 }
186 
187 // Test is flaky http://crbug.com/301887.
IN_PROC_BROWSER_TEST_F(DesktopCaptureApiTest,DISABLED_Delegation)188 IN_PROC_BROWSER_TEST_F(DesktopCaptureApiTest, DISABLED_Delegation) {
189   // Initialize test server.
190   base::FilePath test_data;
191   EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data));
192   embedded_test_server()->ServeFilesFromDirectory(test_data.AppendASCII(
193       "extensions/api_test/desktop_capture_delegate"));
194   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
195   host_resolver()->AddRule("*", embedded_test_server()->base_url().host());
196 
197   // Load extension.
198   base::FilePath extension_path =
199       test_data_dir_.AppendASCII("desktop_capture_delegate");
200   const Extension* extension = LoadExtensionWithFlags(
201       extension_path, ExtensionBrowserTest::kFlagNone);
202   ASSERT_TRUE(extension);
203 
204   ui_test_utils::NavigateToURL(
205       browser(), GetURLForPath("example.com", "/example.com.html"));
206 
207   TestFlags test_flags[] = {
208     { true, true,
209       content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0) },
210     { true, true,
211       content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0) },
212     { true, true,
213       content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0), true },
214   };
215   picker_factory_.SetTestFlags(test_flags, arraysize(test_flags));
216 
217   bool result;
218 
219   content::WebContents* web_contents =
220       browser()->tab_strip_model()->GetActiveWebContents();
221 
222   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
223       web_contents, "getStream()", &result));
224   EXPECT_TRUE(result);
225 
226   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
227       web_contents, "getStreamWithInvalidId()", &result));
228   EXPECT_TRUE(result);
229 
230   // Verify that the picker is closed once the tab is closed.
231   content::WebContentsDestroyedWatcher destroyed_watcher(web_contents);
232   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
233       web_contents, "openPickerDialogAndReturn()", &result));
234   EXPECT_TRUE(result);
235   EXPECT_TRUE(test_flags[2].picker_created);
236   EXPECT_FALSE(test_flags[2].picker_deleted);
237 
238   web_contents->Close();
239   destroyed_watcher.Wait();
240   EXPECT_TRUE(test_flags[2].picker_deleted);
241 }
242 
243 }  // namespace extensions
244