Skip to content

Commit 0c7246f

Browse files
committed
[test] add test for Cannot screenshare from within iframe Cross domain. InvalidStateError nwjs#6212
1 parent 3ed9b2a commit 0c7246f

File tree

5 files changed

+272
-0
lines changed

5 files changed

+272
-0
lines changed

src/nwjs_browsertest.cc

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,17 @@
101101
#include "chrome/browser/printing/print_preview_dialog_controller.h"
102102
#include "content/browser/frame_host/render_frame_host_impl.h"
103103

104+
#include "chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h"
105+
#include "chrome/browser/media/webrtc/fake_desktop_media_list.h"
106+
#include "chrome/common/chrome_paths.h"
107+
#include "chrome/common/chrome_switches.h"
108+
#include "chrome/test/base/ui_test_utils.h"
109+
#include "content/public/test/browser_test_utils.h"
110+
#include "extensions/common/switches.h"
111+
#include "net/dns/mock_host_resolver.h"
112+
#include "net/test/embedded_test_server/embedded_test_server.h"
113+
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h"
114+
104115
#if defined(ENABLE_PLUGINS)
105116
#include "content/public/browser/plugin_service.h"
106117
#include "content/public/common/webplugininfo.h"
@@ -1093,3 +1104,180 @@ IN_PROC_BROWSER_TEST_P(NWJSWebViewTest, LocalPDF) {
10931104
}
10941105
}
10951106

1107+
using content::DesktopMediaID;
1108+
1109+
namespace {
1110+
1111+
struct TestFlags {
1112+
bool expect_screens;
1113+
bool expect_windows;
1114+
bool expect_tabs;
1115+
bool expect_audio;
1116+
content::DesktopMediaID selected_source;
1117+
bool cancelled;
1118+
1119+
// Following flags are set by FakeDesktopMediaPicker when it's created and
1120+
// deleted.
1121+
bool picker_created;
1122+
bool picker_deleted;
1123+
};
1124+
1125+
class FakeDesktopMediaPicker : public DesktopMediaPicker {
1126+
public:
1127+
explicit FakeDesktopMediaPicker(TestFlags* expectation)
1128+
: expectation_(expectation),
1129+
weak_factory_(this) {
1130+
expectation_->picker_created = true;
1131+
}
1132+
~FakeDesktopMediaPicker() override { expectation_->picker_deleted = true; }
1133+
1134+
// DesktopMediaPicker interface.
1135+
void Show(content::WebContents* web_contents,
1136+
gfx::NativeWindow context,
1137+
gfx::NativeWindow parent,
1138+
const base::string16& app_name,
1139+
const base::string16& target_name,
1140+
std::vector<std::unique_ptr<DesktopMediaList>> source_lists,
1141+
bool request_audio,
1142+
const DoneCallback& done_callback) override {
1143+
bool show_screens = false;
1144+
bool show_windows = false;
1145+
bool show_tabs = false;
1146+
1147+
for (auto& source_list : source_lists) {
1148+
switch (source_list->GetMediaListType()) {
1149+
case DesktopMediaID::TYPE_NONE:
1150+
break;
1151+
case DesktopMediaID::TYPE_SCREEN:
1152+
show_screens = true;
1153+
break;
1154+
case DesktopMediaID::TYPE_WINDOW:
1155+
show_windows = true;
1156+
break;
1157+
case DesktopMediaID::TYPE_WEB_CONTENTS:
1158+
show_tabs = true;
1159+
break;
1160+
}
1161+
}
1162+
EXPECT_EQ(expectation_->expect_screens, show_screens);
1163+
EXPECT_EQ(expectation_->expect_windows, show_windows);
1164+
EXPECT_EQ(expectation_->expect_tabs, show_tabs);
1165+
EXPECT_EQ(expectation_->expect_audio, request_audio);
1166+
1167+
if (!expectation_->cancelled) {
1168+
// Post a task to call the callback asynchronously.
1169+
base::ThreadTaskRunnerHandle::Get()->PostTask(
1170+
FROM_HERE, base::BindOnce(&FakeDesktopMediaPicker::CallCallback,
1171+
weak_factory_.GetWeakPtr(), done_callback));
1172+
} else {
1173+
// If we expect the dialog to be cancelled then store the callback to
1174+
// retain reference to the callback handler.
1175+
done_callback_ = done_callback;
1176+
}
1177+
}
1178+
1179+
private:
1180+
void CallCallback(DoneCallback done_callback) {
1181+
done_callback.Run(expectation_->selected_source);
1182+
}
1183+
1184+
TestFlags* expectation_;
1185+
DoneCallback done_callback_;
1186+
1187+
base::WeakPtrFactory<FakeDesktopMediaPicker> weak_factory_;
1188+
1189+
DISALLOW_COPY_AND_ASSIGN(FakeDesktopMediaPicker);
1190+
};
1191+
1192+
class FakeDesktopMediaPickerFactory :
1193+
public extensions::DesktopCaptureChooseDesktopMediaFunction::PickerFactory {
1194+
public:
1195+
FakeDesktopMediaPickerFactory() {}
1196+
~FakeDesktopMediaPickerFactory() override {}
1197+
1198+
void SetTestFlags(TestFlags* test_flags, int tests_count) {
1199+
test_flags_ = test_flags;
1200+
tests_count_ = tests_count;
1201+
current_test_ = 0;
1202+
}
1203+
1204+
std::unique_ptr<DesktopMediaPicker> CreatePicker() override {
1205+
EXPECT_LE(current_test_, tests_count_);
1206+
if (current_test_ >= tests_count_)
1207+
return std::unique_ptr<DesktopMediaPicker>();
1208+
++current_test_;
1209+
return std::unique_ptr<DesktopMediaPicker>(
1210+
new FakeDesktopMediaPicker(test_flags_ + current_test_ - 1));
1211+
}
1212+
1213+
std::unique_ptr<DesktopMediaList> CreateMediaList(
1214+
DesktopMediaID::Type type) override {
1215+
EXPECT_LE(current_test_, tests_count_);
1216+
return std::unique_ptr<DesktopMediaList>(new FakeDesktopMediaList(type));
1217+
}
1218+
1219+
private:
1220+
TestFlags* test_flags_;
1221+
int tests_count_;
1222+
int current_test_;
1223+
1224+
DISALLOW_COPY_AND_ASSIGN(FakeDesktopMediaPickerFactory);
1225+
};
1226+
1227+
class NWDesktopCaptureApiTest : public NWAppTest {
1228+
public:
1229+
NWDesktopCaptureApiTest() {
1230+
extensions::DesktopCaptureChooseDesktopMediaFunction::
1231+
SetPickerFactoryForTests(&picker_factory_);
1232+
}
1233+
~NWDesktopCaptureApiTest() override {
1234+
extensions::DesktopCaptureChooseDesktopMediaFunction::
1235+
SetPickerFactoryForTests(NULL);
1236+
}
1237+
1238+
void SetUpOnMainThread() override {
1239+
NWAppTest::SetUpOnMainThread();
1240+
host_resolver()->AddRule("*", "127.0.0.1");
1241+
}
1242+
1243+
protected:
1244+
GURL GetURLForPath(const std::string& host, const std::string& path) {
1245+
std::string port = base::UintToString(embedded_test_server()->port());
1246+
GURL::Replacements replacements;
1247+
replacements.SetHostStr(host);
1248+
replacements.SetPortStr(port);
1249+
return embedded_test_server()->GetURL(path).ReplaceComponents(replacements);
1250+
}
1251+
1252+
FakeDesktopMediaPickerFactory picker_factory_;
1253+
};
1254+
1255+
} // namespace
1256+
1257+
IN_PROC_BROWSER_TEST_F(NWJSDesktopCaptureApiTest, CrossDomain) {
1258+
TestFlags test_flags[] = {
1259+
{true, false, false, false,
1260+
content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
1261+
content::DesktopMediaID::kNullId), false},
1262+
};
1263+
picker_factory_.SetTestFlags(test_flags, arraysize(test_flags));
1264+
base::FilePath test_dir = test_data_dir_.Append(FILE_PATH_LITERAL("platform_apps")).Append(FILE_PATH_LITERAL("6212-crossdomain-screen"));
1265+
embedded_test_server()->ServeFilesFromDirectory(test_dir);
1266+
ASSERT_TRUE(embedded_test_server()->Start());
1267+
1268+
net::HostPortPair host_and_port = embedded_test_server()->host_port_pair();
1269+
LoadAndLaunchPlatformApp("6212-crossdomain-screen", "Launched");
1270+
content::WebContents* web_contents = GetFirstAppWindowWebContents();
1271+
ASSERT_TRUE(web_contents);
1272+
ExtensionTestMessageListener listener("Loaded", false);
1273+
ASSERT_TRUE(content::ExecuteScript(web_contents, "document.getElementById('frame0').src='" +
1274+
embedded_test_server()->GetURL("/remote.html").spec() + "'"));
1275+
EXPECT_TRUE(listener.WaitUntilSatisfied()) << "'" << listener.message()
1276+
<< "' message was not receieved";
1277+
std::vector<content::RenderFrameHost*> frames = web_contents->GetAllFrames();
1278+
ASSERT_TRUE(frames.size() == 2);
1279+
content::ExecuteScriptAndGetValue(frames[1], "document.getElementById('testbtn').click()");
1280+
ExtensionTestMessageListener pass_listener("Pass", false);
1281+
EXPECT_TRUE(pass_listener.WaitUntilSatisfied()) << "'" << pass_listener.message()
1282+
<< "' message was not receieved";
1283+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
function chooseDesktopMedia(){
2+
if(nw.Screen.Init){
3+
nw.Screen.Init();
4+
}
5+
nw.Screen.chooseDesktopMedia(["screen"],function(streamId){
6+
if(streamId) {
7+
var conf = {
8+
mandatory: {
9+
chromeMediaSource: 'desktop',
10+
chromeMediaSourceId: streamId,
11+
maxWidth: 1920,
12+
maxHeight: 1080
13+
},
14+
optional: []
15+
};
16+
console.log("[nw.chooseDesktopMedia] stream id:" + streamId);
17+
showScreenShare({audio: false, video: conf});
18+
}
19+
})
20+
}
21+
22+
function showScreenShare(conf){
23+
var ve = document.getElementById("screen-share");
24+
25+
navigator.mediaDevices.getUserMedia(conf)
26+
.then(function(stream){
27+
var url = window.URL.createObjectURL(stream);
28+
ve.src = url;
29+
if (chrome.test) {
30+
chrome.test.sendMessage("Pass");
31+
}
32+
})
33+
.catch(function(e){
34+
console.log(e);
35+
if (chrome.test) {
36+
chrome.test.sendMessage("Fail");
37+
}else{
38+
alert(e);
39+
}
40+
});
41+
42+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5+
<title></title>
6+
<script type="text/javascript" src="demo.js"></script>
7+
<link rel="stylesheet" type="text/css" href="demo.css" >
8+
</head>
9+
<body>
10+
<iframe id="frame0" src="about:blank" style="width:100%; height:400px;"></iframe>
11+
<script>
12+
if (chrome.test) {
13+
document.getElementById("frame0").onload = function() { chrome.test.sendMessage("Loaded"); };
14+
chrome.test.sendMessage("Launched");
15+
}
16+
</script>
17+
</body>
18+
</html>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "6212",
3+
"main": "index.html",
4+
"nodejs":true,
5+
"chromium-args": "--unsafely-treat-insecure-origin-as-secure=http://*****:8080",
6+
"node-remote": "<all_urls>"
7+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5+
<title></title>
6+
<script type="text/javascript" src="demo.js"></script>
7+
<link rel="stylesheet" type="text/css" href="demo.css" >
8+
</head>
9+
<body>
10+
<div class="screen-share-demo">
11+
<video id="screen-share" autoplay></video>
12+
<div class="tools">
13+
<button id="testbtn" onclick="chooseDesktopMedia()">screen.chooseDesktopMedia</button>
14+
</div>
15+
</div>
16+
</body>
17+
</html>

0 commit comments

Comments
 (0)