1// Copyright 2014 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 "content/shell/renderer/test_runner/mock_web_user_media_client.h"
6
7#include "base/logging.h"
8#include "base/macros.h"
9#include "content/shell/renderer/test_runner/mock_constraints.h"
10#include "content/shell/renderer/test_runner/web_test_delegate.h"
11#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
12#include "third_party/WebKit/public/platform/WebMediaDeviceInfo.h"
13#include "third_party/WebKit/public/platform/WebMediaStream.h"
14#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
15#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
16#include "third_party/WebKit/public/platform/WebMediaStreamTrackSourcesRequest.h"
17#include "third_party/WebKit/public/platform/WebSourceInfo.h"
18#include "third_party/WebKit/public/platform/WebVector.h"
19#include "third_party/WebKit/public/web/WebDocument.h"
20#include "third_party/WebKit/public/web/WebMediaDevicesRequest.h"
21#include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
22#include "third_party/WebKit/public/web/WebUserMediaRequest.h"
23
24using blink::WebMediaConstraints;
25using blink::WebMediaDeviceInfo;
26using blink::WebMediaDevicesRequest;
27using blink::WebMediaStream;
28using blink::WebMediaStreamSource;
29using blink::WebMediaStreamTrack;
30using blink::WebMediaStreamTrackSourcesRequest;
31using blink::WebSourceInfo;
32using blink::WebString;
33using blink::WebUserMediaRequest;
34using blink::WebVector;
35
36namespace content {
37
38class UserMediaRequestTask : public WebMethodTask<MockWebUserMediaClient> {
39 public:
40  UserMediaRequestTask(MockWebUserMediaClient* object,
41                       const WebUserMediaRequest& request,
42                       const WebMediaStream result)
43      : WebMethodTask<MockWebUserMediaClient>(object),
44        request_(request),
45        result_(result) {
46    DCHECK(!result_.isNull());
47  }
48
49  virtual void RunIfValid() OVERRIDE { request_.requestSucceeded(result_); }
50
51 private:
52  WebUserMediaRequest request_;
53  WebMediaStream result_;
54
55  DISALLOW_COPY_AND_ASSIGN(UserMediaRequestTask);
56};
57
58class UserMediaRequestConstraintFailedTask
59    : public WebMethodTask<MockWebUserMediaClient> {
60 public:
61  UserMediaRequestConstraintFailedTask(MockWebUserMediaClient* object,
62                                       const WebUserMediaRequest& request,
63                                       const WebString& constraint)
64      : WebMethodTask<MockWebUserMediaClient>(object),
65        request_(request),
66        constraint_(constraint) {}
67
68  virtual void RunIfValid() OVERRIDE {
69    request_.requestFailedConstraint(constraint_);
70  }
71
72 private:
73  WebUserMediaRequest request_;
74  WebString constraint_;
75
76  DISALLOW_COPY_AND_ASSIGN(UserMediaRequestConstraintFailedTask);
77};
78
79class UserMediaRequestPermissionDeniedTask
80    : public WebMethodTask<MockWebUserMediaClient> {
81 public:
82  UserMediaRequestPermissionDeniedTask(MockWebUserMediaClient* object,
83                                       const WebUserMediaRequest& request)
84      : WebMethodTask<MockWebUserMediaClient>(object),
85        request_(request) {}
86
87  virtual void RunIfValid() OVERRIDE { request_.requestFailed(); }
88
89 private:
90  WebUserMediaRequest request_;
91
92  DISALLOW_COPY_AND_ASSIGN(UserMediaRequestPermissionDeniedTask);
93};
94
95class MediaDevicesRequestTask : public WebMethodTask<MockWebUserMediaClient> {
96 public:
97  MediaDevicesRequestTask(MockWebUserMediaClient* object,
98                          const WebMediaDevicesRequest& request,
99                          const WebVector<WebMediaDeviceInfo>& result)
100      : WebMethodTask<MockWebUserMediaClient>(object),
101        request_(request),
102        result_(result) {}
103
104  virtual void RunIfValid() OVERRIDE { request_.requestSucceeded(result_); }
105
106 private:
107  WebMediaDevicesRequest request_;
108  WebVector<WebMediaDeviceInfo> result_;
109
110  DISALLOW_COPY_AND_ASSIGN(MediaDevicesRequestTask);
111};
112
113class SourcesRequestTask : public WebMethodTask<MockWebUserMediaClient> {
114 public:
115  SourcesRequestTask(MockWebUserMediaClient* object,
116                     const WebMediaStreamTrackSourcesRequest& request,
117                     const WebVector<WebSourceInfo>& result)
118      : WebMethodTask<MockWebUserMediaClient>(object),
119        request_(request),
120        result_(result) {}
121
122  virtual void RunIfValid() OVERRIDE { request_.requestSucceeded(result_); }
123
124 private:
125  WebMediaStreamTrackSourcesRequest request_;
126  WebVector<WebSourceInfo> result_;
127
128  DISALLOW_COPY_AND_ASSIGN(SourcesRequestTask);
129};
130
131class MockExtraData : public WebMediaStream::ExtraData {
132 public:
133  int foo;
134};
135
136MockWebUserMediaClient::MockWebUserMediaClient(WebTestDelegate* delegate)
137    : delegate_(delegate) {}
138
139void MockWebUserMediaClient::requestUserMedia(
140    const WebUserMediaRequest& stream_request) {
141    DCHECK(!stream_request.isNull());
142    WebUserMediaRequest request = stream_request;
143
144    if (request.ownerDocument().isNull() || !request.ownerDocument().frame()) {
145      delegate_->PostTask(
146          new UserMediaRequestPermissionDeniedTask(this, request));
147        return;
148    }
149
150    WebMediaConstraints constraints = request.audioConstraints();
151    WebString failed_constraint;
152    if (!constraints.isNull() &&
153        !MockConstraints::VerifyConstraints(constraints, &failed_constraint)) {
154      delegate_->PostTask(new UserMediaRequestConstraintFailedTask(
155          this, request, failed_constraint));
156      return;
157    }
158    constraints = request.videoConstraints();
159    if (!constraints.isNull() &&
160        !MockConstraints::VerifyConstraints(constraints, &failed_constraint)) {
161      delegate_->PostTask(new UserMediaRequestConstraintFailedTask(
162          this, request, failed_constraint));
163      return;
164    }
165
166    const size_t zero = 0;
167    const size_t one = 1;
168    WebVector<WebMediaStreamTrack> audio_tracks(request.audio() ? one : zero);
169    WebVector<WebMediaStreamTrack> video_tracks(request.video() ? one : zero);
170
171    if (request.audio()) {
172      WebMediaStreamSource source;
173      source.initialize("MockAudioDevice#1",
174                        WebMediaStreamSource::TypeAudio,
175                        "Mock audio device");
176      audio_tracks[0].initialize(source);
177    }
178
179    if (request.video()) {
180      WebMediaStreamSource source;
181      source.initialize("MockVideoDevice#1",
182                        WebMediaStreamSource::TypeVideo,
183                        "Mock video device");
184      video_tracks[0].initialize(source);
185    }
186
187    WebMediaStream stream;
188    stream.initialize(audio_tracks, video_tracks);
189
190    stream.setExtraData(new MockExtraData());
191
192    delegate_->PostTask(new UserMediaRequestTask(this, request, stream));
193}
194
195void MockWebUserMediaClient::cancelUserMediaRequest(
196    const WebUserMediaRequest&) {
197}
198
199void MockWebUserMediaClient::requestMediaDevices(
200    const WebMediaDevicesRequest& request) {
201  struct {
202    const char* device_id;
203    WebMediaDeviceInfo::MediaDeviceKind kind;
204    const char* label;
205    const char* group_id;
206  } test_devices[] = {
207    {
208      "device1",
209      WebMediaDeviceInfo::MediaDeviceKindAudioInput,
210      "Built-in microphone",
211      "group1",
212    },
213    {
214      "device2",
215      WebMediaDeviceInfo::MediaDeviceKindAudioOutput,
216      "Built-in speakers",
217      "group1",
218    },
219    {
220      "device3",
221      WebMediaDeviceInfo::MediaDeviceKindVideoInput,
222      "Build-in webcam",
223      "group2",
224    },
225  };
226
227  WebVector<WebMediaDeviceInfo> devices(ARRAYSIZE_UNSAFE(test_devices));
228  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_devices); ++i) {
229    devices[i].initialize(WebString::fromUTF8(test_devices[i].device_id),
230                          test_devices[i].kind,
231                          WebString::fromUTF8(test_devices[i].label),
232                          WebString::fromUTF8(test_devices[i].group_id));
233  }
234
235  delegate_->PostTask(new MediaDevicesRequestTask(this, request, devices));
236}
237
238void MockWebUserMediaClient::cancelMediaDevicesRequest(
239    const WebMediaDevicesRequest&) {
240}
241
242void MockWebUserMediaClient::requestSources(
243    const blink::WebMediaStreamTrackSourcesRequest& request) {
244  struct {
245    const char* id;
246    WebSourceInfo::SourceKind kind;
247    const char* label;
248    WebSourceInfo::VideoFacingMode facing;
249  } test_sources[] = {
250    {
251      "device1",
252      WebSourceInfo::SourceKindAudio,
253      "Built-in microphone",
254      WebSourceInfo::VideoFacingModeNone,
255    },
256    {
257      "device2",
258      WebSourceInfo::SourceKindVideo,
259      "Build-in webcam",
260      WebSourceInfo::VideoFacingModeEnvironment,
261    },
262  };
263
264  WebVector<WebSourceInfo> sources(ARRAYSIZE_UNSAFE(test_sources));
265  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_sources); ++i) {
266  sources[i].initialize(WebString::fromUTF8(test_sources[i].id),
267                        test_sources[i].kind,
268                        WebString::fromUTF8(test_sources[i].label),
269                        test_sources[i].facing);
270  }
271
272  delegate_->PostTask(new SourcesRequestTask(this, request, sources));
273}
274
275}  // namespace content
276