| OLD | NEW | 
|    1 /* |    1 /* | 
|    2  * Copyright (C) 2011 Ericsson AB. All rights reserved. |    2  * Copyright (C) 2011 Ericsson AB. All rights reserved. | 
|    3  * Copyright (C) 2012 Google Inc. All rights reserved. |    3  * Copyright (C) 2012 Google Inc. All rights reserved. | 
|    4  * |    4  * | 
|    5  * Redistribution and use in source and binary forms, with or without |    5  * Redistribution and use in source and binary forms, with or without | 
|    6  * modification, are permitted provided that the following conditions |    6  * modification, are permitted provided that the following conditions | 
|    7  * are met: |    7  * are met: | 
|    8  * |    8  * | 
|    9  * 1. Redistributions of source code must retain the above copyright |    9  * 1. Redistributions of source code must retain the above copyright | 
|   10  *    notice, this list of conditions and the following disclaimer. |   10  *    notice, this list of conditions and the following disclaimer. | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
|   24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |   24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
|   25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |   25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
|   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
|   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
|   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
|   29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |   29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|   30  */ |   30  */ | 
|   31  |   31  | 
|   32 #include "modules/mediastream/UserMediaRequest.h" |   32 #include "modules/mediastream/UserMediaRequest.h" | 
|   33  |   33  | 
 |   34 #include <type_traits> | 
 |   35  | 
|   34 #include "bindings/core/v8/Dictionary.h" |   36 #include "bindings/core/v8/Dictionary.h" | 
|   35 #include "bindings/core/v8/ExceptionMessages.h" |   37 #include "bindings/core/v8/ExceptionMessages.h" | 
|   36 #include "bindings/core/v8/ExceptionState.h" |   38 #include "bindings/core/v8/ExceptionState.h" | 
|   37 #include "core/dom/Document.h" |   39 #include "core/dom/Document.h" | 
|   38 #include "core/dom/ExceptionCode.h" |   40 #include "core/dom/ExceptionCode.h" | 
|   39 #include "core/dom/SpaceSplitString.h" |   41 #include "core/dom/SpaceSplitString.h" | 
|   40 #include "core/frame/Deprecation.h" |   42 #include "core/frame/Deprecation.h" | 
|   41 #include "core/frame/HostsUsingFeatures.h" |   43 #include "core/frame/HostsUsingFeatures.h" | 
|   42 #include "modules/mediastream/MediaConstraintsImpl.h" |   44 #include "modules/mediastream/MediaConstraintsImpl.h" | 
|   43 #include "modules/mediastream/MediaStream.h" |   45 #include "modules/mediastream/MediaStream.h" | 
|   44 #include "modules/mediastream/MediaStreamConstraints.h" |   46 #include "modules/mediastream/MediaStreamConstraints.h" | 
|   45 #include "modules/mediastream/MediaTrackConstraints.h" |   47 #include "modules/mediastream/MediaTrackConstraints.h" | 
|   46 #include "modules/mediastream/UserMediaController.h" |   48 #include "modules/mediastream/UserMediaController.h" | 
|   47 #include "platform/mediastream/MediaStreamCenter.h" |   49 #include "platform/mediastream/MediaStreamCenter.h" | 
|   48 #include "platform/mediastream/MediaStreamDescriptor.h" |   50 #include "platform/mediastream/MediaStreamDescriptor.h" | 
|   49  |   51  | 
|   50 namespace blink { |   52 namespace blink { | 
|   51  |   53  | 
|   52 static WebMediaConstraints ParseOptions( |   54 namespace { | 
|   53     ExecutionContext* context, |   55  | 
|   54     const BooleanOrMediaTrackConstraints& options, |   56 template <typename NumericConstraint> | 
|   55     MediaErrorState& error_state) { |   57 bool SetUsesNumericConstraint( | 
 |   58     const WebMediaTrackConstraintSet& set, | 
 |   59     NumericConstraint WebMediaTrackConstraintSet::*field) { | 
 |   60   return (set.*field).HasExact() || (set.*field).HasIdeal() || | 
 |   61          (set.*field).HasMin() || (set.*field).HasMax(); | 
 |   62 } | 
 |   63  | 
 |   64 template <typename DiscreteConstraint> | 
 |   65 bool SetUsesDiscreteConstraint( | 
 |   66     const WebMediaTrackConstraintSet& set, | 
 |   67     DiscreteConstraint WebMediaTrackConstraintSet::*field) { | 
 |   68   return (set.*field).HasExact() || (set.*field).HasIdeal(); | 
 |   69 } | 
 |   70  | 
 |   71 template <typename NumericConstraint> | 
 |   72 bool RequestUsesNumericConstraint( | 
 |   73     const WebMediaConstraints& constraints, | 
 |   74     NumericConstraint WebMediaTrackConstraintSet::*field) { | 
 |   75   if (SetUsesNumericConstraint(constraints.Basic(), field)) | 
 |   76     return true; | 
 |   77   for (const auto& advanced_set : constraints.Advanced()) { | 
 |   78     if (SetUsesNumericConstraint(advanced_set, field)) | 
 |   79       return true; | 
 |   80   } | 
 |   81   return false; | 
 |   82 } | 
 |   83  | 
 |   84 template <typename DiscreteConstraint> | 
 |   85 bool RequestUsesDiscreteConstraint( | 
 |   86     const WebMediaConstraints& constraints, | 
 |   87     DiscreteConstraint WebMediaTrackConstraintSet::*field) { | 
 |   88   static_assert( | 
 |   89       std::is_same<decltype(field), | 
 |   90                    StringConstraint WebMediaTrackConstraintSet::*>::value || | 
 |   91           std::is_same<decltype(field), | 
 |   92                        BooleanConstraint WebMediaTrackConstraintSet::*>::value, | 
 |   93       "Must use StringConstraint or BooleanConstraint"); | 
 |   94   if (SetUsesDiscreteConstraint(constraints.Basic(), field)) | 
 |   95     return true; | 
 |   96   for (const auto& advanced_set : constraints.Advanced()) { | 
 |   97     if (SetUsesDiscreteConstraint(advanced_set, field)) | 
 |   98       return true; | 
 |   99   } | 
 |  100   return false; | 
 |  101 } | 
 |  102  | 
 |  103 class FeatureCounter { | 
 |  104   WTF_MAKE_NONCOPYABLE(FeatureCounter); | 
 |  105  | 
 |  106  public: | 
 |  107   FeatureCounter(ExecutionContext* context) | 
 |  108       : context_(context), is_unconstrained_(true) {} | 
 |  109   void Count(UseCounter::Feature feature) { | 
 |  110     UseCounter::Count(context_, feature); | 
 |  111     is_unconstrained_ = false; | 
 |  112   } | 
 |  113   bool IsUnconstrained() { return is_unconstrained_; } | 
 |  114  | 
 |  115  private: | 
 |  116   Persistent<ExecutionContext> context_; | 
 |  117   bool is_unconstrained_; | 
 |  118 }; | 
 |  119  | 
 |  120 void CountAudioConstraintUses(ExecutionContext* context, | 
 |  121                               const WebMediaConstraints& constraints) { | 
 |  122   FeatureCounter counter(context); | 
 |  123   if (RequestUsesNumericConstraint(constraints, | 
 |  124                                    &WebMediaTrackConstraintSet::sample_rate)) { | 
 |  125     counter.Count(UseCounter::kMediaStreamConstraintsSampleRate); | 
 |  126   } | 
 |  127   if (RequestUsesNumericConstraint(constraints, | 
 |  128                                    &WebMediaTrackConstraintSet::sample_size)) { | 
 |  129     counter.Count(UseCounter::kMediaStreamConstraintsSampleSize); | 
 |  130   } | 
 |  131   if (RequestUsesDiscreteConstraint( | 
 |  132           constraints, &WebMediaTrackConstraintSet::echo_cancellation)) { | 
 |  133     counter.Count(UseCounter::kMediaStreamConstraintsEchoCancellation); | 
 |  134   } | 
 |  135   if (RequestUsesNumericConstraint(constraints, | 
 |  136                                    &WebMediaTrackConstraintSet::latency)) { | 
 |  137     counter.Count(UseCounter::kMediaStreamConstraintsLatency); | 
 |  138   } | 
 |  139   if (RequestUsesNumericConstraint( | 
 |  140           constraints, &WebMediaTrackConstraintSet::channel_count)) { | 
 |  141     counter.Count(UseCounter::kMediaStreamConstraintsChannelCount); | 
 |  142   } | 
 |  143   if (RequestUsesDiscreteConstraint(constraints, | 
 |  144                                     &WebMediaTrackConstraintSet::device_id)) { | 
 |  145     counter.Count(UseCounter::kMediaStreamConstraintsDeviceIdAudio); | 
 |  146   } | 
 |  147   if (RequestUsesDiscreteConstraint( | 
 |  148           constraints, &WebMediaTrackConstraintSet::disable_local_echo)) { | 
 |  149     counter.Count(UseCounter::kMediaStreamConstraintsDisableLocalEcho); | 
 |  150   } | 
 |  151   if (RequestUsesDiscreteConstraint(constraints, | 
 |  152                                     &WebMediaTrackConstraintSet::group_id)) { | 
 |  153     counter.Count(UseCounter::kMediaStreamConstraintsGroupIdAudio); | 
 |  154   } | 
 |  155   if (RequestUsesDiscreteConstraint( | 
 |  156           constraints, &WebMediaTrackConstraintSet::media_stream_source)) { | 
 |  157     counter.Count(UseCounter::kMediaStreamConstraintsMediaStreamSourceAudio); | 
 |  158   } | 
 |  159   if (RequestUsesDiscreteConstraint( | 
 |  160           constraints, | 
 |  161           &WebMediaTrackConstraintSet::render_to_associated_sink)) { | 
 |  162     counter.Count(UseCounter::kMediaStreamConstraintsRenderToAssociatedSink); | 
 |  163   } | 
 |  164   if (RequestUsesDiscreteConstraint( | 
 |  165           constraints, &WebMediaTrackConstraintSet::hotword_enabled)) { | 
 |  166     counter.Count(UseCounter::kMediaStreamConstraintsHotwordEnabled); | 
 |  167   } | 
 |  168   if (RequestUsesDiscreteConstraint( | 
 |  169           constraints, &WebMediaTrackConstraintSet::goog_echo_cancellation)) { | 
 |  170     counter.Count(UseCounter::kMediaStreamConstraintsGoogEchoCancellation); | 
 |  171   } | 
 |  172   if (RequestUsesDiscreteConstraint( | 
 |  173           constraints, | 
 |  174           &WebMediaTrackConstraintSet::goog_experimental_echo_cancellation)) { | 
 |  175     counter.Count( | 
 |  176         UseCounter::kMediaStreamConstraintsGoogExperimentalEchoCancellation); | 
 |  177   } | 
 |  178   if (RequestUsesDiscreteConstraint( | 
 |  179           constraints, &WebMediaTrackConstraintSet::goog_auto_gain_control)) { | 
 |  180     counter.Count(UseCounter::kMediaStreamConstraintsGoogAutoGainControl); | 
 |  181   } | 
 |  182   if (RequestUsesDiscreteConstraint( | 
 |  183           constraints, | 
 |  184           &WebMediaTrackConstraintSet::goog_experimental_auto_gain_control)) { | 
 |  185     counter.Count( | 
 |  186         UseCounter::kMediaStreamConstraintsGoogExperimentalAutoGainControl); | 
 |  187   } | 
 |  188   if (RequestUsesDiscreteConstraint( | 
 |  189           constraints, &WebMediaTrackConstraintSet::goog_noise_suppression)) { | 
 |  190     counter.Count(UseCounter::kMediaStreamConstraintsGoogNoiseSuppression); | 
 |  191   } | 
 |  192   if (RequestUsesDiscreteConstraint( | 
 |  193           constraints, &WebMediaTrackConstraintSet::goog_highpass_filter)) { | 
 |  194     counter.Count(UseCounter::kMediaStreamConstraintsGoogHighpassFilter); | 
 |  195   } | 
 |  196   if (RequestUsesDiscreteConstraint( | 
 |  197           constraints, | 
 |  198           &WebMediaTrackConstraintSet::goog_typing_noise_detection)) { | 
 |  199     counter.Count(UseCounter::kMediaStreamConstraintsGoogTypingNoiseDetection); | 
 |  200   } | 
 |  201   if (RequestUsesDiscreteConstraint( | 
 |  202           constraints, | 
 |  203           &WebMediaTrackConstraintSet::goog_experimental_noise_suppression)) { | 
 |  204     counter.Count( | 
 |  205         UseCounter::kMediaStreamConstraintsGoogExperimentalNoiseSuppression); | 
 |  206   } | 
 |  207   if (RequestUsesDiscreteConstraint( | 
 |  208           constraints, &WebMediaTrackConstraintSet::goog_beamforming)) { | 
 |  209     counter.Count(UseCounter::kMediaStreamConstraintsGoogBeamforming); | 
 |  210   } | 
 |  211   if (RequestUsesDiscreteConstraint( | 
 |  212           constraints, &WebMediaTrackConstraintSet::goog_array_geometry)) { | 
 |  213     counter.Count(UseCounter::kMediaStreamConstraintsGoogArrayGeometry); | 
 |  214   } | 
 |  215   if (RequestUsesDiscreteConstraint( | 
 |  216           constraints, &WebMediaTrackConstraintSet::goog_audio_mirroring)) { | 
 |  217     counter.Count(UseCounter::kMediaStreamConstraintsGoogAudioMirroring); | 
 |  218   } | 
 |  219   if (RequestUsesDiscreteConstraint( | 
 |  220           constraints, | 
 |  221           &WebMediaTrackConstraintSet::goog_da_echo_cancellation)) { | 
 |  222     counter.Count(UseCounter::kMediaStreamConstraintsGoogDAEchoCancellation); | 
 |  223   } | 
 |  224  | 
 |  225   UseCounter::Count(context, UseCounter::kMediaStreamConstraintsAudio); | 
 |  226   if (counter.IsUnconstrained()) { | 
 |  227     UseCounter::Count(context, | 
 |  228                       UseCounter::kMediaStreamConstraintsAudioUnconstrained); | 
 |  229   } | 
 |  230 } | 
 |  231  | 
 |  232 void CountVideoConstraintUses(ExecutionContext* context, | 
 |  233                               const WebMediaConstraints& constraints) { | 
 |  234   FeatureCounter counter(context); | 
 |  235   if (RequestUsesNumericConstraint(constraints, | 
 |  236                                    &WebMediaTrackConstraintSet::width)) { | 
 |  237     counter.Count(UseCounter::kMediaStreamConstraintsWidth); | 
 |  238   } | 
 |  239   if (RequestUsesNumericConstraint(constraints, | 
 |  240                                    &WebMediaTrackConstraintSet::height)) { | 
 |  241     counter.Count(UseCounter::kMediaStreamConstraintsHeight); | 
 |  242   } | 
 |  243   if (RequestUsesNumericConstraint(constraints, | 
 |  244                                    &WebMediaTrackConstraintSet::aspect_ratio)) { | 
 |  245     counter.Count(UseCounter::kMediaStreamConstraintsAspectRatio); | 
 |  246   } | 
 |  247   if (RequestUsesNumericConstraint(constraints, | 
 |  248                                    &WebMediaTrackConstraintSet::frame_rate)) { | 
 |  249     counter.Count(UseCounter::kMediaStreamConstraintsFrameRate); | 
 |  250   } | 
 |  251   if (RequestUsesDiscreteConstraint(constraints, | 
 |  252                                     &WebMediaTrackConstraintSet::facing_mode)) { | 
 |  253     counter.Count(UseCounter::kMediaStreamConstraintsFacingMode); | 
 |  254   } | 
 |  255   if (RequestUsesDiscreteConstraint(constraints, | 
 |  256                                     &WebMediaTrackConstraintSet::device_id)) { | 
 |  257     counter.Count(UseCounter::kMediaStreamConstraintsDeviceIdVideo); | 
 |  258   } | 
 |  259   if (RequestUsesDiscreteConstraint(constraints, | 
 |  260                                     &WebMediaTrackConstraintSet::group_id)) { | 
 |  261     counter.Count(UseCounter::kMediaStreamConstraintsGroupIdVideo); | 
 |  262   } | 
 |  263   if (RequestUsesDiscreteConstraint(constraints, | 
 |  264                                     &WebMediaTrackConstraintSet::video_kind)) { | 
 |  265     counter.Count(UseCounter::kMediaStreamConstraintsVideoKind); | 
 |  266   } | 
 |  267   if (RequestUsesNumericConstraint(constraints, | 
 |  268                                    &WebMediaTrackConstraintSet::depth_near)) { | 
 |  269     counter.Count(UseCounter::kMediaStreamConstraintsDepthNear); | 
 |  270   } | 
 |  271   if (RequestUsesNumericConstraint(constraints, | 
 |  272                                    &WebMediaTrackConstraintSet::depth_far)) { | 
 |  273     counter.Count(UseCounter::kMediaStreamConstraintsDepthFar); | 
 |  274   } | 
 |  275   if (RequestUsesNumericConstraint( | 
 |  276           constraints, &WebMediaTrackConstraintSet::focal_length_x)) { | 
 |  277     counter.Count(UseCounter::kMediaStreamConstraintsFocalLengthX); | 
 |  278   } | 
 |  279   if (RequestUsesNumericConstraint( | 
 |  280           constraints, &WebMediaTrackConstraintSet::focal_length_y)) { | 
 |  281     counter.Count(UseCounter::kMediaStreamConstraintsFocalLengthY); | 
 |  282   } | 
 |  283   if (RequestUsesDiscreteConstraint( | 
 |  284           constraints, &WebMediaTrackConstraintSet::media_stream_source)) { | 
 |  285     counter.Count(UseCounter::kMediaStreamConstraintsMediaStreamSourceVideo); | 
 |  286   } | 
 |  287   if (RequestUsesDiscreteConstraint( | 
 |  288           constraints, &WebMediaTrackConstraintSet::goog_noise_reduction)) { | 
 |  289     counter.Count(UseCounter::kMediaStreamConstraintsGoogNoiseReduction); | 
 |  290   } | 
 |  291   if (RequestUsesNumericConstraint( | 
 |  292           constraints, | 
 |  293           &WebMediaTrackConstraintSet::goog_power_line_frequency)) { | 
 |  294     counter.Count(UseCounter::kMediaStreamConstraintsGoogPowerLineFrequency); | 
 |  295   } | 
 |  296  | 
 |  297   UseCounter::Count(context, UseCounter::kMediaStreamConstraintsVideo); | 
 |  298   if (counter.IsUnconstrained()) { | 
 |  299     UseCounter::Count(context, | 
 |  300                       UseCounter::kMediaStreamConstraintsVideoUnconstrained); | 
 |  301   } | 
 |  302 } | 
 |  303  | 
 |  304 WebMediaConstraints ParseOptions(ExecutionContext* context, | 
 |  305                                  const BooleanOrMediaTrackConstraints& options, | 
 |  306                                  MediaErrorState& error_state) { | 
|   56   WebMediaConstraints constraints; |  307   WebMediaConstraints constraints; | 
|   57  |  308  | 
|   58   Dictionary constraints_dictionary; |  309   Dictionary constraints_dictionary; | 
|   59   if (options.isNull()) { |  310   if (options.isNull()) { | 
|   60     // Do nothing. |  311     // Do nothing. | 
|   61   } else if (options.isMediaTrackConstraints()) { |  312   } else if (options.isMediaTrackConstraints()) { | 
|   62     constraints = MediaConstraintsImpl::Create( |  313     constraints = MediaConstraintsImpl::Create( | 
|   63         context, options.getAsMediaTrackConstraints(), error_state); |  314         context, options.getAsMediaTrackConstraints(), error_state); | 
|   64   } else { |  315   } else { | 
|   65     DCHECK(options.isBoolean()); |  316     DCHECK(options.isBoolean()); | 
|   66     if (options.getAsBoolean()) { |  317     if (options.getAsBoolean()) { | 
|   67       constraints = MediaConstraintsImpl::Create(); |  318       constraints = MediaConstraintsImpl::Create(); | 
|   68     } |  319     } | 
|   69   } |  320   } | 
|   70  |  321  | 
|   71   return constraints; |  322   return constraints; | 
|   72 } |  323 } | 
|   73  |  324  | 
 |  325 }  // namespace | 
 |  326  | 
|   74 UserMediaRequest* UserMediaRequest::Create( |  327 UserMediaRequest* UserMediaRequest::Create( | 
|   75     ExecutionContext* context, |  328     ExecutionContext* context, | 
|   76     UserMediaController* controller, |  329     UserMediaController* controller, | 
|   77     const MediaStreamConstraints& options, |  330     const MediaStreamConstraints& options, | 
|   78     NavigatorUserMediaSuccessCallback* success_callback, |  331     NavigatorUserMediaSuccessCallback* success_callback, | 
|   79     NavigatorUserMediaErrorCallback* error_callback, |  332     NavigatorUserMediaErrorCallback* error_callback, | 
|   80     MediaErrorState& error_state) { |  333     MediaErrorState& error_state) { | 
|   81   WebMediaConstraints audio = |  334   WebMediaConstraints audio = | 
|   82       ParseOptions(context, options.audio(), error_state); |  335       ParseOptions(context, options.audio(), error_state); | 
|   83   if (error_state.HadException()) |  336   if (error_state.HadException()) | 
|   84     return nullptr; |  337     return nullptr; | 
|   85  |  338  | 
|   86   WebMediaConstraints video = |  339   WebMediaConstraints video = | 
|   87       ParseOptions(context, options.video(), error_state); |  340       ParseOptions(context, options.video(), error_state); | 
|   88   if (error_state.HadException()) |  341   if (error_state.HadException()) | 
|   89     return nullptr; |  342     return nullptr; | 
|   90  |  343  | 
|   91   if (audio.IsNull() && video.IsNull()) { |  344   if (audio.IsNull() && video.IsNull()) { | 
|   92     error_state.ThrowTypeError( |  345     error_state.ThrowTypeError( | 
|   93         "At least one of audio and video must be requested"); |  346         "At least one of audio and video must be requested"); | 
|   94     return nullptr; |  347     return nullptr; | 
|   95   } |  348   } | 
|   96  |  349  | 
 |  350   if (!audio.IsNull()) | 
 |  351     CountAudioConstraintUses(context, audio); | 
 |  352   if (!video.IsNull()) | 
 |  353     CountVideoConstraintUses(context, video); | 
 |  354  | 
|   97   return new UserMediaRequest(context, controller, audio, video, |  355   return new UserMediaRequest(context, controller, audio, video, | 
|   98                               success_callback, error_callback); |  356                               success_callback, error_callback); | 
|   99 } |  357 } | 
|  100  |  358  | 
|  101 UserMediaRequest* UserMediaRequest::CreateForTesting( |  359 UserMediaRequest* UserMediaRequest::CreateForTesting( | 
|  102     const WebMediaConstraints& audio, |  360     const WebMediaConstraints& audio, | 
|  103     const WebMediaConstraints& video) { |  361     const WebMediaConstraints& video) { | 
|  104   return new UserMediaRequest(nullptr, nullptr, audio, video, nullptr, nullptr); |  362   return new UserMediaRequest(nullptr, nullptr, audio, video, nullptr, nullptr); | 
|  105 } |  363 } | 
|  106  |  364  | 
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  232 } |  490 } | 
|  233  |  491  | 
|  234 DEFINE_TRACE(UserMediaRequest) { |  492 DEFINE_TRACE(UserMediaRequest) { | 
|  235   visitor->Trace(controller_); |  493   visitor->Trace(controller_); | 
|  236   visitor->Trace(success_callback_); |  494   visitor->Trace(success_callback_); | 
|  237   visitor->Trace(error_callback_); |  495   visitor->Trace(error_callback_); | 
|  238   ContextLifecycleObserver::Trace(visitor); |  496   ContextLifecycleObserver::Trace(visitor); | 
|  239 } |  497 } | 
|  240  |  498  | 
|  241 }  // namespace blink |  499 }  // namespace blink | 
| OLD | NEW |