1// Copyright (c) 2012 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#ifndef CONTENT_RENDERER_MEDIA_USER_MEDIA_CLIENT_IMPL_H_
6#define CONTENT_RENDERER_MEDIA_USER_MEDIA_CLIENT_IMPL_H_
7
8#include <string>
9#include <vector>
10
11#include "base/basictypes.h"
12#include "base/compiler_specific.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/memory/scoped_vector.h"
16#include "base/memory/weak_ptr.h"
17#include "base/threading/non_thread_safe.h"
18#include "content/common/content_export.h"
19#include "content/public/renderer/render_frame_observer.h"
20#include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
21#include "content/renderer/media/media_stream_source.h"
22#include "third_party/WebKit/public/platform/WebMediaStream.h"
23#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
24#include "third_party/WebKit/public/platform/WebSourceInfo.h"
25#include "third_party/WebKit/public/platform/WebVector.h"
26#include "third_party/WebKit/public/web/WebMediaDevicesRequest.h"
27#include "third_party/WebKit/public/web/WebUserMediaClient.h"
28#include "third_party/WebKit/public/web/WebUserMediaRequest.h"
29#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
30
31namespace content {
32class PeerConnectionDependencyFactory;
33class MediaStreamDispatcher;
34class MediaStreamVideoSource;
35class VideoCapturerDelegate;
36
37// UserMediaClientImpl is a delegate for the Media Stream GetUserMedia API.
38// It ties together WebKit and MediaStreamManager
39// (via MediaStreamDispatcher and MediaStreamDispatcherHost)
40// in the browser process. It must be created, called and destroyed on the
41// render thread.
42class CONTENT_EXPORT UserMediaClientImpl
43    : public RenderFrameObserver,
44      NON_EXPORTED_BASE(public blink::WebUserMediaClient),
45      public MediaStreamDispatcherEventHandler,
46      NON_EXPORTED_BASE(public base::NonThreadSafe) {
47 public:
48  // |render_frame| and |dependency_factory| must outlive this instance.
49  UserMediaClientImpl(
50      RenderFrame* render_frame,
51      PeerConnectionDependencyFactory* dependency_factory,
52      scoped_ptr<MediaStreamDispatcher> media_stream_dispatcher);
53  virtual ~UserMediaClientImpl();
54
55  MediaStreamDispatcher* media_stream_dispatcher() const {
56    return media_stream_dispatcher_.get();
57  }
58
59  // blink::WebUserMediaClient implementation
60  virtual void requestUserMedia(
61      const blink::WebUserMediaRequest& user_media_request);
62  virtual void cancelUserMediaRequest(
63      const blink::WebUserMediaRequest& user_media_request);
64  virtual void requestMediaDevices(
65      const blink::WebMediaDevicesRequest& media_devices_request) OVERRIDE;
66  virtual void cancelMediaDevicesRequest(
67      const blink::WebMediaDevicesRequest& media_devices_request) OVERRIDE;
68  virtual void requestSources(
69      const blink::WebMediaStreamTrackSourcesRequest& sources_request) OVERRIDE;
70
71  // MediaStreamDispatcherEventHandler implementation.
72  virtual void OnStreamGenerated(
73      int request_id,
74      const std::string& label,
75      const StreamDeviceInfoArray& audio_array,
76      const StreamDeviceInfoArray& video_array) OVERRIDE;
77  virtual void OnStreamGenerationFailed(
78      int request_id,
79      MediaStreamRequestResult result) OVERRIDE;
80  virtual void OnDeviceStopped(const std::string& label,
81                               const StreamDeviceInfo& device_info) OVERRIDE;
82  virtual void OnDevicesEnumerated(
83      int request_id,
84      const StreamDeviceInfoArray& device_array) OVERRIDE;
85  virtual void OnDeviceOpened(
86      int request_id,
87      const std::string& label,
88      const StreamDeviceInfo& device_info) OVERRIDE;
89  virtual void OnDeviceOpenFailed(int request_id) OVERRIDE;
90
91  // RenderFrameObserver OVERRIDE
92  virtual void FrameWillClose() OVERRIDE;
93
94 protected:
95  // Called when |source| has been stopped from JavaScript.
96  void OnLocalSourceStopped(const blink::WebMediaStreamSource& source);
97
98  // These methods are virtual for test purposes. A test can override them to
99  // test requesting local media streams. The function notifies WebKit that the
100  // |request| have completed.
101  virtual void GetUserMediaRequestSucceeded(
102       const blink::WebMediaStream& stream,
103       blink::WebUserMediaRequest* request_info);
104  virtual void GetUserMediaRequestFailed(
105      blink::WebUserMediaRequest* request_info,
106      MediaStreamRequestResult result);
107  virtual void GetUserMediaRequestTrackStartedFailed(
108      blink::WebUserMediaRequest* request_info,
109      MediaStreamRequestResult result,
110      const blink::WebString& result_name);
111  virtual void EnumerateDevicesSucceded(
112      blink::WebMediaDevicesRequest* request,
113      blink::WebVector<blink::WebMediaDeviceInfo>& devices);
114  virtual void EnumerateSourcesSucceded(
115      blink::WebMediaStreamTrackSourcesRequest* request,
116      blink::WebVector<blink::WebSourceInfo>& sources);
117  // Creates a MediaStreamVideoSource object.
118  // This is virtual for test purposes.
119  virtual MediaStreamVideoSource* CreateVideoSource(
120      const StreamDeviceInfo& device,
121      const MediaStreamSource::SourceStoppedCallback& stop_callback);
122
123 private:
124  // Class for storing information about a WebKit request to create a
125  // MediaStream.
126  class UserMediaRequestInfo
127      : public base::SupportsWeakPtr<UserMediaRequestInfo> {
128   public:
129    typedef base::Callback<void(UserMediaRequestInfo* request_info,
130                                MediaStreamRequestResult result,
131                                const blink::WebString& result_name)>
132      ResourcesReady;
133
134    UserMediaRequestInfo(int request_id,
135                         const blink::WebUserMediaRequest& request,
136                         bool enable_automatic_output_device_selection);
137    ~UserMediaRequestInfo();
138    int request_id;
139    // True if MediaStreamDispatcher has generated the stream, see
140    // OnStreamGenerated.
141    bool generated;
142    const bool enable_automatic_output_device_selection;
143    blink::WebMediaStream web_stream;
144    blink::WebUserMediaRequest request;
145
146    void StartAudioTrack(const blink::WebMediaStreamTrack& track,
147                         const blink::WebMediaConstraints& constraints);
148
149    blink::WebMediaStreamTrack CreateAndStartVideoTrack(
150        const blink::WebMediaStreamSource& source,
151        const blink::WebMediaConstraints& constraints);
152
153    // Triggers |callback| when all sources used in this request have either
154    // successfully started, or a source has failed to start.
155    void CallbackOnTracksStarted(const ResourcesReady& callback);
156
157    bool IsSourceUsed(const blink::WebMediaStreamSource& source) const;
158    void RemoveSource(const blink::WebMediaStreamSource& source);
159
160    bool HasPendingSources() const;
161
162   private:
163    void OnTrackStarted(
164        MediaStreamSource* source,
165        MediaStreamRequestResult result,
166        const blink::WebString& result_name);
167    void CheckAllTracksStarted();
168
169    ResourcesReady ready_callback_;
170    MediaStreamRequestResult request_result_;
171    blink::WebString request_result_name_;
172    // Sources used in this request.
173    std::vector<blink::WebMediaStreamSource> sources_;
174    std::vector<MediaStreamSource*> sources_waiting_for_callback_;
175  };
176  typedef ScopedVector<UserMediaRequestInfo> UserMediaRequests;
177
178  typedef std::vector<blink::WebMediaStreamSource> LocalStreamSources;
179
180  struct MediaDevicesRequestInfo;
181  typedef ScopedVector<MediaDevicesRequestInfo> MediaDevicesRequests;
182
183  // Creates a WebKit representation of stream sources based on
184  // |devices| from the MediaStreamDispatcher.
185  void InitializeSourceObject(
186      const StreamDeviceInfo& device,
187      blink::WebMediaStreamSource::Type type,
188      const blink::WebMediaConstraints& constraints,
189      blink::WebMediaStreamSource* webkit_source);
190
191  void CreateVideoTracks(
192      const StreamDeviceInfoArray& devices,
193      const blink::WebMediaConstraints& constraints,
194      blink::WebVector<blink::WebMediaStreamTrack>* webkit_tracks,
195      UserMediaRequestInfo* request);
196
197  void CreateAudioTracks(
198      const StreamDeviceInfoArray& devices,
199      const blink::WebMediaConstraints& constraints,
200      blink::WebVector<blink::WebMediaStreamTrack>* webkit_tracks,
201      UserMediaRequestInfo* request);
202
203  // Callback function triggered when all native versions of the
204  // underlying media sources and tracks have been created and started.
205  void OnCreateNativeTracksCompleted(
206      UserMediaRequestInfo* request,
207      MediaStreamRequestResult result,
208      const blink::WebString& result_name);
209
210  void OnStreamGeneratedForCancelledRequest(
211      const StreamDeviceInfoArray& audio_array,
212      const StreamDeviceInfoArray& video_array);
213
214  void FinalizeEnumerateDevices(MediaDevicesRequestInfo* request);
215  void FinalizeEnumerateSources(MediaDevicesRequestInfo* request);
216
217  UserMediaRequestInfo* FindUserMediaRequestInfo(int request_id);
218  UserMediaRequestInfo* FindUserMediaRequestInfo(
219      const blink::WebUserMediaRequest& request);
220  void DeleteUserMediaRequestInfo(UserMediaRequestInfo* request);
221  void DeleteAllUserMediaRequests();
222
223  MediaDevicesRequestInfo* FindMediaDevicesRequestInfo(int request_id);
224  MediaDevicesRequestInfo* FindMediaDevicesRequestInfo(
225      const blink::WebMediaDevicesRequest& request);
226  void CancelAndDeleteMediaDevicesRequest(MediaDevicesRequestInfo* request);
227
228  // Returns the source that use a device with |device.session_id|
229  // and |device.device.id|. NULL if such source doesn't exist.
230  const blink::WebMediaStreamSource* FindLocalSource(
231      const StreamDeviceInfo& device) const;
232
233  void StopLocalSource(const blink::WebMediaStreamSource& source,
234                       bool notify_dispatcher);
235
236  // Weak ref to a PeerConnectionDependencyFactory, owned by the RenderThread.
237  // It's valid for the lifetime of RenderThread.
238  // TODO(xians): Remove this dependency once audio do not need it for local
239  // audio.
240  PeerConnectionDependencyFactory* const dependency_factory_;
241
242  // UserMediaClientImpl owns MediaStreamDispatcher instead of RenderFrameImpl
243  // (or RenderFrameObserver) to ensure tear-down occurs in the right order.
244  const scoped_ptr<MediaStreamDispatcher> media_stream_dispatcher_;
245
246  LocalStreamSources local_sources_;
247
248  UserMediaRequests user_media_requests_;
249
250  // Requests to enumerate media devices.
251  MediaDevicesRequests media_devices_requests_;
252
253  // Note: This member must be the last to ensure all outstanding weak pointers
254  // are invalidated first.
255  base::WeakPtrFactory<UserMediaClientImpl> weak_factory_;
256
257  DISALLOW_COPY_AND_ASSIGN(UserMediaClientImpl);
258};
259
260}  // namespace content
261
262#endif  // CONTENT_RENDERER_MEDIA_USER_MEDIA_CLIENT_IMPL_H_
263