Browse Source

refactor: desktop capturer module (#14835)

* Revert "post all desktop capturer apis to worker threads"

This reverts commit 5a28759fea358c117c55121c1cd370abd143a207.

* refactor: desktop capturer module

* Creates the screen and window capturer for the liftime of the app
* Fixes incorrect usage of weak ptr

* build: add //ui/snapshot to chromium_src deps

* fix: handle scenarios when there are no captured sources
Robo 6 years ago
parent
commit
596ae2c2df

+ 112 - 97
atom/browser/api/atom_api_desktop_capturer.cc

@@ -8,20 +8,17 @@
 #include <utility>
 #include <vector>
 
-using base::PlatformThreadRef;
-
 #include "atom/common/api/atom_api_native_image.h"
 #include "atom/common/native_mate_converters/gfx_converter.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "chrome/browser/media/desktop_media_list.h"
-#include "content/public/browser/browser_thread.h"
+#include "base/threading/thread_restrictions.h"
+#include "chrome/browser/media/webrtc/desktop_media_list.h"
 #include "content/public/browser/desktop_capture.h"
 #include "native_mate/dictionary.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
+
 #if defined(OS_WIN)
 #include "third_party/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h"
 #include "third_party/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
@@ -51,63 +48,121 @@ struct Converter<atom::api::DesktopCapturer::Source> {
 
 }  // namespace mate
 
-namespace {
+namespace atom {
 
-void EmitFinished(
-    const std::vector<atom::api::DesktopCapturer::Source>& sources,
-    atom::api::DesktopCapturer* cap) {
-  cap->Emit("finished", sources);
+namespace api {
+
+DesktopCapturer::DesktopCapturer(v8::Isolate* isolate) {
+  Init(isolate);
 }
 
-void StartHandlingTask(bool capture_window,
-                       bool capture_screen,
-                       const gfx::Size& thumbnail_size,
-                       atom::api::DesktopCapturer* cap) {
+DesktopCapturer::~DesktopCapturer() {}
+
+void DesktopCapturer::StartHandling(bool capture_window,
+                                    bool capture_screen,
+                                    const gfx::Size& thumbnail_size) {
 #if defined(OS_WIN)
   if (content::desktop_capture::CreateDesktopCaptureOptions()
           .allow_directx_capturer()) {
     // DxgiDuplicatorController should be alive in this scope according to
     // screen_capturer_win.cc.
     auto duplicator = webrtc::DxgiDuplicatorController::Instance();
-    cap->using_directx_capturer_ =
-        webrtc::ScreenCapturerWinDirectx::IsSupported();
+    using_directx_capturer_ = webrtc::ScreenCapturerWinDirectx::IsSupported();
   }
 #endif  // defined(OS_WIN)
-  std::unique_ptr<webrtc::DesktopCapturer> screen_capturer(
-      capture_screen ? content::desktop_capture::CreateScreenCapturer()
-                     : nullptr);
-  std::unique_ptr<webrtc::DesktopCapturer> window_capturer(
-      capture_window ? content::desktop_capture::CreateWindowCapturer()
-                     : nullptr);
-  cap->media_list_.reset(new NativeDesktopMediaList(
-      std::move(screen_capturer), std::move(window_capturer)));
-
-  cap->media_list_->SetThumbnailSize(thumbnail_size);
-  cap->media_list_->StartUpdating(cap);
+
+  // clear any existing captured sources.
+  captured_sources_.clear();
+
+  // Start listening for captured sources.
+  capture_window_ = capture_window;
+  capture_screen_ = capture_screen;
+
+  {
+    // Remove this once
+    // https://bugs.chromium.org/p/chromium/issues/detail?id=795340 is fixed.
+    base::ScopedAllowBaseSyncPrimitivesForTesting
+        scoped_allow_base_sync_primitives;
+    // Initialize the source list.
+    // Apply the new thumbnail size and restart capture.
+    if (capture_window) {
+      window_capturer_.reset(new NativeDesktopMediaList(
+          content::DesktopMediaID::TYPE_WINDOW,
+          content::desktop_capture::CreateWindowCapturer()));
+      window_capturer_->SetThumbnailSize(thumbnail_size);
+      window_capturer_->AddObserver(this);
+      window_capturer_->StartUpdating();
+    }
+
+    if (capture_screen) {
+      screen_capturer_.reset(new NativeDesktopMediaList(
+          content::DesktopMediaID::TYPE_SCREEN,
+          content::desktop_capture::CreateScreenCapturer()));
+      screen_capturer_->SetThumbnailSize(thumbnail_size);
+      screen_capturer_->AddObserver(this);
+      screen_capturer_->StartUpdating();
+    }
+  }
+}
+
+void DesktopCapturer::OnSourceAdded(DesktopMediaList* list, int index) {}
+
+void DesktopCapturer::OnSourceRemoved(DesktopMediaList* list, int index) {}
+
+void DesktopCapturer::OnSourceMoved(DesktopMediaList* list,
+                                    int old_index,
+                                    int new_index) {}
+
+void DesktopCapturer::OnSourceNameChanged(DesktopMediaList* list, int index) {}
+
+void DesktopCapturer::OnSourceThumbnailChanged(DesktopMediaList* list,
+                                               int index) {}
+
+void DesktopCapturer::OnSourceUnchanged(DesktopMediaList* list) {
+  UpdateSourcesList(list);
 }
 
-void OnRefreshFinishedTask(atom::api::DesktopCapturer* cap) {
-  const auto media_list_sources = cap->media_list_->GetSources();
-  std::vector<atom::api::DesktopCapturer::Source> sources;
-  for (const auto& media_list_source : media_list_sources) {
-    sources.emplace_back(
-        atom::api::DesktopCapturer::Source{media_list_source, std::string()});
+bool DesktopCapturer::ShouldScheduleNextRefresh(DesktopMediaList* list) {
+  UpdateSourcesList(list);
+  return false;
+}
+
+void DesktopCapturer::UpdateSourcesList(DesktopMediaList* list) {
+  std::vector<DesktopCapturer::Source> window_sources;
+  if (capture_window_ &&
+      list->GetMediaListType() == content::DesktopMediaID::TYPE_WINDOW) {
+    capture_window_ = false;
+    const auto& media_list_sources = list->GetSources();
+    for (const auto& media_list_source : media_list_sources) {
+      window_sources.emplace_back(
+          DesktopCapturer::Source{media_list_source, std::string()});
+    }
+    std::move(window_sources.begin(), window_sources.end(),
+              std::back_inserter(captured_sources_));
   }
 
+  std::vector<DesktopCapturer::Source> screen_sources;
+  if (capture_screen_ &&
+      list->GetMediaListType() == content::DesktopMediaID::TYPE_SCREEN) {
+    capture_screen_ = false;
+    const auto& media_list_sources = list->GetSources();
+    for (const auto& media_list_source : media_list_sources) {
+      screen_sources.emplace_back(
+          DesktopCapturer::Source{media_list_source, std::string()});
+    }
 #if defined(OS_WIN)
-  // Gather the same unique screen IDs used by the electron.screen API in order
-  // to provide an association between it and desktopCapturer/getUserMedia.
-  // This is only required when using the DirectX capturer, otherwise the IDs
-  // across the APIs already match.
-  if (cap->using_directx_capturer_) {
-    std::vector<std::string> device_names;
-    // Crucially, this list of device names will be in the same order as
-    // |media_list_sources|.
-    webrtc::DxgiDuplicatorController::Instance()->GetDeviceNames(&device_names);
-    int device_name_index = 0;
-    for (auto& source : sources) {
-      if (source.media_list_source.id.type ==
-          content::DesktopMediaID::TYPE_SCREEN) {
+    // Gather the same unique screen IDs used by the electron.screen API in
+    // order to provide an association between it and
+    // desktopCapturer/getUserMedia. This is only required when using the
+    // DirectX capturer, otherwise the IDs across the APIs already match.
+    if (using_directx_capturer_) {
+      std::vector<std::string> device_names;
+      // Crucially, this list of device names will be in the same order as
+      // |media_list_sources|.
+      webrtc::DxgiDuplicatorController::Instance()->GetDeviceNames(
+          &device_names);
+      int device_name_index = 0;
+      for (auto& source : screen_sources) {
         const auto& device_name = device_names[device_name_index++];
         std::wstring wide_device_name;
         base::UTF8ToWide(device_name.c_str(), device_name.size(),
@@ -118,61 +173,21 @@ void OnRefreshFinishedTask(atom::api::DesktopCapturer* cap) {
         source.display_id = base::Int64ToString(device_id);
       }
     }
-  }
 #elif defined(OS_MACOSX)
-  // On Mac, the IDs across the APIs match.
-  for (auto& source : sources) {
-    if (source.media_list_source.id.type ==
-        content::DesktopMediaID::TYPE_SCREEN) {
+    // On Mac, the IDs across the APIs match.
+    for (auto& source : screen_sources) {
       source.display_id = base::Int64ToString(source.media_list_source.id.id);
     }
-  }
 #endif  // defined(OS_WIN)
-  // TODO(ajmacd): Add Linux support. The IDs across APIs differ but Chrome only
-  // supports capturing the entire desktop on Linux. Revisit this if individual
-  // screen support is added.
-
-  content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
-                                   base::Bind(EmitFinished, sources, cap));
-}
-
-}  // namespace
-
-namespace atom {
-
-namespace api {
-
-DesktopCapturer::DesktopCapturer(v8::Isolate* isolate) {
-  Init(isolate);
-  capture_thread_ = base::CreateSequencedTaskRunnerWithTraits(
-      {base::WithBaseSyncPrimitives(), base::MayBlock(),
-       base::TaskPriority::USER_VISIBLE});
-}
-
-DesktopCapturer::~DesktopCapturer() {}
-
-void DesktopCapturer::StartHandling(bool capture_window,
-                                    bool capture_screen,
-                                    const gfx::Size& thumbnail_size) {
-  capture_thread_->PostTask(
-      FROM_HERE, base::BindOnce(StartHandlingTask, capture_window,
-                                capture_screen, thumbnail_size, this));
-}
-
-void DesktopCapturer::OnSourceAdded(int index) {}
-
-void DesktopCapturer::OnSourceRemoved(int index) {}
-
-void DesktopCapturer::OnSourceMoved(int old_index, int new_index) {}
-
-void DesktopCapturer::OnSourceNameChanged(int index) {}
-
-void DesktopCapturer::OnSourceThumbnailChanged(int index) {}
+    // TODO(ajmacd): Add Linux support. The IDs across APIs differ but Chrome
+    // only supports capturing the entire desktop on Linux. Revisit this if
+    // individual screen support is added.
+    std::move(screen_sources.begin(), screen_sources.end(),
+              std::back_inserter(captured_sources_));
+  }
 
-bool DesktopCapturer::OnRefreshFinished() {
-  capture_thread_->PostTask(FROM_HERE,
-                            base::BindOnce(OnRefreshFinishedTask, this));
-  return false;
+  if (!capture_window_ && !capture_screen_)
+    Emit("finished", captured_sources_);
 }
 
 // static

+ 22 - 14
atom/browser/api/atom_api_desktop_capturer.h

@@ -7,10 +7,11 @@
 
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "atom/browser/api/event_emitter.h"
-#include "chrome/browser/media/desktop_media_list_observer.h"
-#include "chrome/browser/media/native_desktop_media_list.h"
+#include "chrome/browser/media/webrtc/desktop_media_list_observer.h"
+#include "chrome/browser/media/webrtc/native_desktop_media_list.h"
 #include "native_mate/handle.h"
 
 namespace atom {
@@ -35,25 +36,32 @@ class DesktopCapturer : public mate::EventEmitter<DesktopCapturer>,
                      bool capture_screen,
                      const gfx::Size& thumbnail_size);
 
-  std::unique_ptr<DesktopMediaList> media_list_;
-#if defined(OS_WIN)
-  bool using_directx_capturer_ = false;
-#endif  // defined(OS_WIN)
-
  protected:
   explicit DesktopCapturer(v8::Isolate* isolate);
   ~DesktopCapturer() override;
 
   // DesktopMediaListObserver overrides.
-  void OnSourceAdded(int index) override;
-  void OnSourceRemoved(int index) override;
-  void OnSourceMoved(int old_index, int new_index) override;
-  void OnSourceNameChanged(int index) override;
-  void OnSourceThumbnailChanged(int index) override;
-  bool OnRefreshFinished() override;
+  void OnSourceAdded(DesktopMediaList* list, int index) override;
+  void OnSourceRemoved(DesktopMediaList* list, int index) override;
+  void OnSourceMoved(DesktopMediaList* list,
+                     int old_index,
+                     int new_index) override;
+  void OnSourceNameChanged(DesktopMediaList* list, int index) override;
+  void OnSourceThumbnailChanged(DesktopMediaList* list, int index) override;
+  void OnSourceUnchanged(DesktopMediaList* list) override;
+  bool ShouldScheduleNextRefresh(DesktopMediaList* list) override;
 
  private:
-  scoped_refptr<base::SequencedTaskRunner> capture_thread_;
+  void UpdateSourcesList(DesktopMediaList* list);
+
+  std::unique_ptr<DesktopMediaList> window_capturer_;
+  std::unique_ptr<DesktopMediaList> screen_capturer_;
+  std::vector<DesktopCapturer::Source> captured_sources_;
+  bool capture_window_ = false;
+  bool capture_screen_ = false;
+#if defined(OS_WIN)
+  bool using_directx_capturer_ = false;
+#endif  // defined(OS_WIN)
 
   DISALLOW_COPY_AND_ASSIGN(DesktopCapturer);
 };

+ 20 - 2
chromium_src/BUILD.gn

@@ -2,6 +2,8 @@
 # Use of this source code is governed by the MIT license that can be
 # found in the LICENSE file.
 
+import("//electron/buildflags/buildflags.gni")
+
 # Builds some of the chrome sources that Electron depends
 # on unconditionally.
 source_set("chrome") {
@@ -10,6 +12,22 @@ source_set("chrome") {
     "//chrome/browser/ssl/security_state_tab_helper.cc",
     "//chrome/browser/ssl/security_state_tab_helper.h",
   ]
-  public_deps = [ "//content/public/browser" ]
-  deps = [ "//components/security_state/content" ]
+  public_deps = [
+    "//content/public/browser",
+  ]
+  deps = [
+    "//components/security_state/content",
+  ]
+
+  if (enable_desktop_capturer) {
+    sources += [
+      "//chrome/browser/media/webrtc/desktop_media_list.h",
+      "//chrome/browser/media/webrtc/desktop_media_list_base.cc",
+      "//chrome/browser/media/webrtc/desktop_media_list_base.h",
+      "//chrome/browser/media/webrtc/desktop_media_list_observer.h",
+      "//chrome/browser/media/webrtc/native_desktop_media_list.cc",
+      "//chrome/browser/media/webrtc/native_desktop_media_list.h",
+    ]
+    deps += [ "//ui/snapshot" ]
+  }
 }

+ 0 - 61
chromium_src/chrome/browser/media/desktop_media_list.h

@@ -1,61 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_MEDIA_DESKTOP_MEDIA_LIST_H_
-#define CHROME_BROWSER_MEDIA_DESKTOP_MEDIA_LIST_H_
-
-#include "base/strings/string16.h"
-#include "base/time/time.h"
-#include "content/public/browser/desktop_media_id.h"
-#include "ui/gfx/image/image_skia.h"
-
-class DesktopMediaListObserver;
-
-// DesktopMediaList provides the list of desktop media source (screens, windows,
-// tabs), and their thumbnails, to the desktop media picker dialog. It
-// transparently updates the list in the background, and notifies the desktop
-// media picker when something changes.
-class DesktopMediaList {
- public:
-  // Struct used to represent each entry in the list.
-  struct Source {
-    // Id of the source.
-    content::DesktopMediaID id;
-
-    // Name of the source that should be shown to the user.
-    base::string16 name;
-
-    // The thumbnail for the source.
-    gfx::ImageSkia thumbnail;
-  };
-
-  virtual ~DesktopMediaList() {}
-
-  // Sets time interval between updates. By default list of sources and their
-  // thumbnail are updated once per second. If called after StartUpdating() then
-  // it will take effect only after the next update.
-  virtual void SetUpdatePeriod(base::TimeDelta period) = 0;
-
-  // Sets size to which the thumbnails should be scaled. If called after
-  // StartUpdating() then some thumbnails may be still scaled to the old size
-  // until they are updated.
-  virtual void SetThumbnailSize(const gfx::Size& thumbnail_size) = 0;
-
-  // Sets ID of the hosting desktop picker dialog. The window with this ID will
-  // be filtered out from the list of sources.
-  virtual void SetViewDialogWindowId(content::DesktopMediaID::Id dialog_id) = 0;
-
-  // Starts updating the model. The model is initially empty, so OnSourceAdded()
-  // notifications will be generated for each existing source as it is
-  // enumerated. After the initial enumeration the model will be refreshed based
-  // on the update period, and notifications generated only for changes in the
-  // model.
-  virtual void StartUpdating(DesktopMediaListObserver* observer) = 0;
-
-  virtual int GetSourceCount() const = 0;
-  virtual const Source& GetSource(int index) const = 0;
-  virtual std::vector<Source> GetSources() const = 0;
-};
-
-#endif  // CHROME_BROWSER_MEDIA_DESKTOP_MEDIA_LIST_H_

+ 0 - 26
chromium_src/chrome/browser/media/desktop_media_list_observer.h

@@ -1,26 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_MEDIA_DESKTOP_MEDIA_LIST_OBSERVER_H_
-#define CHROME_BROWSER_MEDIA_DESKTOP_MEDIA_LIST_OBSERVER_H_
-
-// Interface implemented by the desktop media picker dialog to receive
-// notifications about changes in DesktopMediaList.
-class DesktopMediaListObserver {
- public:
-  virtual void OnSourceAdded(int index) = 0;
-  virtual void OnSourceRemoved(int index) = 0;
-  virtual void OnSourceMoved(int old_index, int new_index) = 0;
-  virtual void OnSourceNameChanged(int index) = 0;
-  virtual void OnSourceThumbnailChanged(int index) = 0;
-
-  // Return false to stop refreshing. The associated |DesktopMediaList| should
-  // no longer be used.
-  virtual bool OnRefreshFinished() = 0;
-
- protected:
-  virtual ~DesktopMediaListObserver() {}
-};
-
-#endif  // CHROME_BROWSER_MEDIA_DESKTOP_MEDIA_LIST_OBSERVER_H_

+ 0 - 367
chromium_src/chrome/browser/media/native_desktop_media_list.cc

@@ -1,367 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/media/native_desktop_media_list.h"
-
-#include <map>
-#include <set>
-#include <sstream>
-
-using base::PlatformThreadRef;
-
-#include "base/hash.h"
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
-#include "chrome/browser/media/desktop_media_list_observer.h"
-#include "content/public/browser/browser_thread.h"
-#include "media/base/video_util.h"
-#include "third_party/libyuv/include/libyuv/scale_argb.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
-#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/gfx/skia_util.h"
-
-using content::BrowserThread;
-using content::DesktopMediaID;
-
-namespace {
-
-// Update the list every second.
-const int kDefaultUpdatePeriod = 1000;
-
-// Returns a hash of a DesktopFrame content to detect when image for a desktop
-// media source has changed.
-uint32_t GetFrameHash(webrtc::DesktopFrame* frame) {
-  int data_size = frame->stride() * frame->size().height();
-  return base::Hash(frame->data(), data_size);
-}
-
-gfx::ImageSkia ScaleDesktopFrame(std::unique_ptr<webrtc::DesktopFrame> frame,
-                                 gfx::Size size) {
-  gfx::Rect scaled_rect = media::ComputeLetterboxRegion(
-      gfx::Rect(0, 0, size.width(), size.height()),
-      gfx::Size(frame->size().width(), frame->size().height()));
-
-  SkBitmap result;
-  result.allocN32Pixels(scaled_rect.width(), scaled_rect.height(), true);
-
-  uint8* pixels_data = reinterpret_cast<uint8*>(result.getPixels());
-  libyuv::ARGBScale(frame->data(), frame->stride(), frame->size().width(),
-                    frame->size().height(), pixels_data, result.rowBytes(),
-                    scaled_rect.width(), scaled_rect.height(),
-                    libyuv::kFilterBilinear);
-
-  // Set alpha channel values to 255 for all pixels.
-  // TODO(sergeyu): Fix screen/window capturers to capture alpha channel and
-  // remove this code. Currently screen/window capturers (at least some
-  // implementations) only capture R, G and B channels and set Alpha to 0.
-  // crbug.com/264424
-  for (int y = 0; y < result.height(); ++y) {
-    for (int x = 0; x < result.width(); ++x) {
-      pixels_data[result.rowBytes() * y + x * result.bytesPerPixel() + 3] =
-          0xff;
-    }
-  }
-
-  return gfx::ImageSkia::CreateFrom1xBitmap(result);
-}
-
-}  // namespace
-
-NativeDesktopMediaList::SourceDescription::SourceDescription(
-    DesktopMediaID id,
-    const base::string16& name)
-    : id(id), name(name) {}
-
-class NativeDesktopMediaList::Worker
-    : public webrtc::DesktopCapturer::Callback {
- public:
-  Worker(base::WeakPtr<NativeDesktopMediaList> media_list,
-         std::unique_ptr<webrtc::DesktopCapturer> screen_capturer,
-         std::unique_ptr<webrtc::DesktopCapturer> window_capturer);
-  ~Worker() override;
-
-  void Refresh(const gfx::Size& thumbnail_size,
-               content::DesktopMediaID::Id view_dialog_id);
-
- private:
-  typedef std::map<DesktopMediaID, uint32> ImageHashesMap;
-
-  // webrtc::DesktopCapturer::Callback interface.
-  void OnCaptureResult(webrtc::DesktopCapturer::Result result,
-                       std::unique_ptr<webrtc::DesktopFrame> frame) override;
-
-  base::WeakPtr<NativeDesktopMediaList> media_list_;
-
-  std::unique_ptr<webrtc::DesktopCapturer> screen_capturer_;
-  std::unique_ptr<webrtc::DesktopCapturer> window_capturer_;
-
-  std::unique_ptr<webrtc::DesktopFrame> current_frame_;
-
-  ImageHashesMap image_hashes_;
-
-  DISALLOW_COPY_AND_ASSIGN(Worker);
-};
-
-NativeDesktopMediaList::Worker::Worker(
-    base::WeakPtr<NativeDesktopMediaList> media_list,
-    std::unique_ptr<webrtc::DesktopCapturer> screen_capturer,
-    std::unique_ptr<webrtc::DesktopCapturer> window_capturer)
-    : media_list_(media_list),
-      screen_capturer_(std::move(screen_capturer)),
-      window_capturer_(std::move(window_capturer)) {
-  if (screen_capturer_)
-    screen_capturer_->Start(this);
-  if (window_capturer_)
-    window_capturer_->Start(this);
-}
-
-NativeDesktopMediaList::Worker::~Worker() {}
-
-void NativeDesktopMediaList::Worker::Refresh(
-    const gfx::Size& thumbnail_size,
-    content::DesktopMediaID::Id view_dialog_id) {
-  std::vector<SourceDescription> sources;
-
-  if (screen_capturer_) {
-    webrtc::DesktopCapturer::SourceList screens;
-    if (screen_capturer_->GetSourceList(&screens)) {
-      bool mutiple_screens = screens.size() > 1;
-      base::string16 title;
-      for (size_t i = 0; i < screens.size(); ++i) {
-        if (mutiple_screens) {
-          title = base::UTF8ToUTF16("Screen " + base::IntToString(i + 1));
-        } else {
-          title = base::UTF8ToUTF16("Entire screen");
-        }
-        sources.push_back(SourceDescription(
-            DesktopMediaID(DesktopMediaID::TYPE_SCREEN, screens[i].id), title));
-      }
-    }
-  }
-
-  if (window_capturer_) {
-    webrtc::DesktopCapturer::SourceList windows;
-    if (window_capturer_->GetSourceList(&windows)) {
-      for (auto it = windows.begin(); it != windows.end(); ++it) {
-        // Skip the picker dialog window.
-        if (it->id != view_dialog_id) {
-          sources.push_back(SourceDescription(
-              DesktopMediaID(DesktopMediaID::TYPE_WINDOW, it->id),
-              base::UTF8ToUTF16(it->title)));
-        }
-      }
-    }
-  }
-  // Update list of windows before updating thumbnails.
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&NativeDesktopMediaList::OnSourcesList, media_list_, sources));
-
-  ImageHashesMap new_image_hashes;
-
-  // Get a thumbnail for each source.
-  for (size_t i = 0; i < sources.size(); ++i) {
-    SourceDescription& source = sources[i];
-    switch (source.id.type) {
-      case DesktopMediaID::TYPE_SCREEN:
-        if (!screen_capturer_->SelectSource(source.id.id))
-          continue;
-        screen_capturer_->CaptureFrame();
-        break;
-
-      case DesktopMediaID::TYPE_WINDOW:
-        if (!window_capturer_->SelectSource(source.id.id))
-          continue;
-        window_capturer_->CaptureFrame();
-        break;
-
-      default:
-        NOTREACHED();
-    }
-
-    // Expect that DesktopCapturer to always captures frames synchronously.
-    // |current_frame_| may be NULL if capture failed (e.g. because window has
-    // been closed).
-    if (current_frame_) {
-      uint32_t frame_hash = GetFrameHash(current_frame_.get());
-      new_image_hashes[source.id] = frame_hash;
-
-      // Scale the image only if it has changed.
-      ImageHashesMap::iterator it = image_hashes_.find(source.id);
-      if (it == image_hashes_.end() || it->second != frame_hash) {
-        gfx::ImageSkia thumbnail =
-            ScaleDesktopFrame(std::move(current_frame_), thumbnail_size);
-        BrowserThread::PostTask(
-            BrowserThread::UI, FROM_HERE,
-            base::Bind(&NativeDesktopMediaList::OnSourceThumbnail, media_list_,
-                       i, thumbnail));
-      }
-    }
-  }
-
-  image_hashes_.swap(new_image_hashes);
-
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&NativeDesktopMediaList::OnRefreshFinished, media_list_));
-
-  // Destroy capturers when done.
-  screen_capturer_.reset();
-  window_capturer_.reset();
-}
-
-void NativeDesktopMediaList::Worker::OnCaptureResult(
-    webrtc::DesktopCapturer::Result result,
-    std::unique_ptr<webrtc::DesktopFrame> frame) {
-  current_frame_ = std::move(frame);
-}
-
-NativeDesktopMediaList::NativeDesktopMediaList(
-    std::unique_ptr<webrtc::DesktopCapturer> screen_capturer,
-    std::unique_ptr<webrtc::DesktopCapturer> window_capturer)
-    : screen_capturer_(std::move(screen_capturer)),
-      window_capturer_(std::move(window_capturer)),
-      update_period_(base::TimeDelta::FromMilliseconds(kDefaultUpdatePeriod)),
-      thumbnail_size_(100, 100),
-      view_dialog_id_(-1),
-      observer_(NULL),
-      weak_factory_(this) {
-  capture_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
-      {base::WithBaseSyncPrimitives(), base::MayBlock(),
-       base::TaskPriority::USER_VISIBLE});
-}
-
-NativeDesktopMediaList::~NativeDesktopMediaList() {
-  capture_task_runner_->DeleteSoon(FROM_HERE, worker_.release());
-}
-
-void NativeDesktopMediaList::SetUpdatePeriod(base::TimeDelta period) {
-  DCHECK(!observer_);
-  update_period_ = period;
-}
-
-void NativeDesktopMediaList::SetThumbnailSize(const gfx::Size& thumbnail_size) {
-  thumbnail_size_ = thumbnail_size;
-}
-
-void NativeDesktopMediaList::SetViewDialogWindowId(
-    content::DesktopMediaID::Id dialog_id) {
-  view_dialog_id_ = dialog_id;
-}
-
-void NativeDesktopMediaList::StartUpdating(DesktopMediaListObserver* observer) {
-  DCHECK(!observer_);
-  DCHECK(screen_capturer_ || window_capturer_);
-
-  observer_ = observer;
-
-  worker_.reset(new Worker(weak_factory_.GetWeakPtr(),
-                           std::move(screen_capturer_),
-                           std::move(window_capturer_)));
-  Refresh();
-}
-
-int NativeDesktopMediaList::GetSourceCount() const {
-  return sources_.size();
-}
-
-const DesktopMediaList::Source& NativeDesktopMediaList::GetSource(
-    int index) const {
-  return sources_[index];
-}
-
-std::vector<DesktopMediaList::Source> NativeDesktopMediaList::GetSources()
-    const {
-  return sources_;
-}
-
-void NativeDesktopMediaList::Refresh() {
-  capture_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&Worker::Refresh, base::Unretained(worker_.get()),
-                            thumbnail_size_, view_dialog_id_));
-}
-
-void NativeDesktopMediaList::OnSourcesList(
-    const std::vector<SourceDescription>& new_sources) {
-  typedef std::set<content::DesktopMediaID> SourceSet;
-  SourceSet new_source_set;
-  for (size_t i = 0; i < new_sources.size(); ++i) {
-    new_source_set.insert(new_sources[i].id);
-  }
-  // Iterate through the old sources to find the removed sources.
-  for (size_t i = 0; i < sources_.size(); ++i) {
-    if (new_source_set.find(sources_[i].id) == new_source_set.end()) {
-      observer_->OnSourceRemoved(i);
-      sources_.erase(sources_.begin() + i);
-      --i;
-    }
-  }
-  // Iterate through the new sources to find the added sources.
-  if (new_sources.size() > sources_.size()) {
-    SourceSet old_source_set;
-    for (size_t i = 0; i < sources_.size(); ++i) {
-      old_source_set.insert(sources_[i].id);
-    }
-
-    for (size_t i = 0; i < new_sources.size(); ++i) {
-      if (old_source_set.find(new_sources[i].id) == old_source_set.end()) {
-        sources_.insert(sources_.begin() + i, Source());
-        sources_[i].id = new_sources[i].id;
-        sources_[i].name = new_sources[i].name;
-        observer_->OnSourceAdded(i);
-      }
-    }
-  }
-  DCHECK_EQ(new_sources.size(), sources_.size());
-
-  // Find the moved/changed sources.
-  size_t pos = 0;
-  while (pos < sources_.size()) {
-    if (!(sources_[pos].id == new_sources[pos].id)) {
-      // Find the source that should be moved to |pos|, starting from |pos + 1|
-      // of |sources_|, because entries before |pos| should have been sorted.
-      size_t old_pos = pos + 1;
-      for (; old_pos < sources_.size(); ++old_pos) {
-        if (sources_[old_pos].id == new_sources[pos].id)
-          break;
-      }
-      DCHECK(sources_[old_pos].id == new_sources[pos].id);
-
-      // Move the source from |old_pos| to |pos|.
-      Source temp = sources_[old_pos];
-      sources_.erase(sources_.begin() + old_pos);
-      sources_.insert(sources_.begin() + pos, temp);
-
-      observer_->OnSourceMoved(old_pos, pos);
-    }
-
-    if (sources_[pos].name != new_sources[pos].name) {
-      sources_[pos].name = new_sources[pos].name;
-      observer_->OnSourceNameChanged(pos);
-    }
-    ++pos;
-  }
-}
-
-void NativeDesktopMediaList::OnSourceThumbnail(int index,
-                                               const gfx::ImageSkia& image) {
-  DCHECK_LT(index, static_cast<int>(sources_.size()));
-  sources_[index].thumbnail = image;
-  observer_->OnSourceThumbnailChanged(index);
-}
-
-void NativeDesktopMediaList::OnRefreshFinished() {
-  // Give a chance to the observer to stop the refresh work.
-  bool is_continue = observer_->OnRefreshFinished();
-  if (is_continue) {
-    BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
-                                   base::Bind(&NativeDesktopMediaList::Refresh,
-                                              weak_factory_.GetWeakPtr()),
-                                   update_period_);
-  }
-}

+ 0 - 98
chromium_src/chrome/browser/media/native_desktop_media_list.h

@@ -1,98 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_MEDIA_NATIVE_DESKTOP_MEDIA_LIST_H_
-#define CHROME_BROWSER_MEDIA_NATIVE_DESKTOP_MEDIA_LIST_H_
-
-#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner.h"
-#include "chrome/browser/media/desktop_media_list.h"
-#include "content/public/browser/desktop_media_id.h"
-#include "ui/gfx/image/image_skia.h"
-
-namespace webrtc {
-class DesktopCapturer;
-}
-
-// Implementation of DesktopMediaList that shows native screens and
-// native windows.
-class NativeDesktopMediaList : public DesktopMediaList {
- public:
-  // Caller may pass NULL for either of the arguments in case when only some
-  // types of sources the model should be populated with (e.g. it will only
-  // contain windows, if |screen_capturer| is NULL).
-  NativeDesktopMediaList(
-      std::unique_ptr<webrtc::DesktopCapturer> screen_capturer,
-      std::unique_ptr<webrtc::DesktopCapturer> window_capturer);
-  ~NativeDesktopMediaList() override;
-
-  // DesktopMediaList interface.
-  void SetUpdatePeriod(base::TimeDelta period) override;
-  void SetThumbnailSize(const gfx::Size& thumbnail_size) override;
-  void StartUpdating(DesktopMediaListObserver* observer) override;
-  int GetSourceCount() const override;
-  const Source& GetSource(int index) const override;
-  std::vector<Source> GetSources() const override;
-  void SetViewDialogWindowId(content::DesktopMediaID::Id dialog_id) override;
-
- private:
-  class Worker;
-  friend class Worker;
-
-  // Struct used to represent sources list the model gets from the Worker.
-  struct SourceDescription {
-    SourceDescription(content::DesktopMediaID id, const base::string16& name);
-
-    content::DesktopMediaID id;
-    base::string16 name;
-  };
-
-  // Order comparator for sources. Used to sort list of sources.
-  static bool CompareSources(const SourceDescription& a,
-                             const SourceDescription& b);
-
-  // Post a task for the |worker_| to update list of windows and get thumbnails.
-  void Refresh();
-
-  // Called by |worker_| to refresh the model. First it posts tasks for
-  // OnSourcesList() with the fresh list of sources, then follows with
-  // OnSourceThumbnail() for each changed thumbnail and then calls
-  // OnRefreshFinished() at the end.
-  void OnSourcesList(const std::vector<SourceDescription>& sources);
-  void OnSourceThumbnail(int index, const gfx::ImageSkia& thumbnail);
-  void OnRefreshFinished();
-
-  // Capturers specified in SetCapturers() and passed to the |worker_| later.
-  std::unique_ptr<webrtc::DesktopCapturer> screen_capturer_;
-  std::unique_ptr<webrtc::DesktopCapturer> window_capturer_;
-
-  // Time interval between mode updates.
-  base::TimeDelta update_period_;
-
-  // Size of thumbnails generated by the model.
-  gfx::Size thumbnail_size_;
-
-  // ID of the hosting dialog.
-  content::DesktopMediaID::Id view_dialog_id_;
-
-  // The observer passed to StartUpdating().
-  DesktopMediaListObserver* observer_;
-
-  // Task runner used for the |worker_|.
-  scoped_refptr<base::SequencedTaskRunner> capture_task_runner_;
-
-  // An object that does all the work of getting list of sources on a background
-  // thread (see |capture_task_runner_|). Destroyed on |capture_task_runner_|
-  // after the model is destroyed.
-  std::unique_ptr<Worker> worker_;
-
-  // Current list of sources.
-  std::vector<Source> sources_;
-
-  base::WeakPtrFactory<NativeDesktopMediaList> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(NativeDesktopMediaList);
-};
-
-#endif  // CHROME_BROWSER_MEDIA_NATIVE_DESKTOP_MEDIA_LIST_H_

+ 0 - 4
filenames.gni

@@ -587,10 +587,6 @@ filenames = {
     "chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.h",
     "chromium_src/chrome/browser/extensions/global_shortcut_listener_win.cc",
     "chromium_src/chrome/browser/extensions/global_shortcut_listener_win.h",
-    "chromium_src/chrome/browser/media/desktop_media_list.h",
-    "chromium_src/chrome/browser/media/desktop_media_list_observer.h",
-    "chromium_src/chrome/browser/media/native_desktop_media_list.cc",
-    "chromium_src/chrome/browser/media/native_desktop_media_list.h",
     "chromium_src/chrome/browser/printing/print_job.cc",
     "chromium_src/chrome/browser/printing/print_job.h",
     "chromium_src/chrome/browser/printing/print_job_manager.cc",

+ 8 - 0
patches/common/chromium/.patches.yaml

@@ -469,3 +469,11 @@ patches:
       * Fixes a main_application_delegate SDK change
       * Fixes a non-null SDK change in a net unittest.
     This is needed for Electron to compile with XCode 10.0.
+-
+  author: deepak1556 <[email protected]>
+  file: desktop_media_list.patch
+  description: |
+    * Adds a new observer method to DesktopMediaListObserver for
+      desktop capture api.
+    * Backports https://chromium-review.googlesource.com/c/chromium/src/+/1199806
+      that fixes crash with screen capturer, can be removed in 71.0.3539.0

+ 304 - 0
patches/common/chromium/desktop_media_list.patch

@@ -0,0 +1,304 @@
+diff --git a/chrome/browser/media/webrtc/desktop_media_list.h b/chrome/browser/media/webrtc/desktop_media_list.h
+index 8e02a8a95eb0..3497b85428a5 100644
+--- a/chrome/browser/media/webrtc/desktop_media_list.h
++++ b/chrome/browser/media/webrtc/desktop_media_list.h
+@@ -32,6 +32,9 @@ class DesktopMediaList {
+ 
+   virtual ~DesktopMediaList() {}
+ 
++  // Allows listening to notifications generated by the model.
++  virtual void AddObserver(DesktopMediaListObserver* observer) = 0;
++
+   // Sets time interval between updates. By default list of sources and their
+   // thumbnail are updated once per second. If called after StartUpdating() then
+   // it will take effect only after the next update.
+@@ -51,10 +54,11 @@ class DesktopMediaList {
+   // enumerated. After the initial enumeration the model will be refreshed based
+   // on the update period, and notifications generated only for changes in the
+   // model.
+-  virtual void StartUpdating(DesktopMediaListObserver* observer) = 0;
++  virtual void StartUpdating() = 0;
+ 
+   virtual int GetSourceCount() const = 0;
+   virtual const Source& GetSource(int index) const = 0;
++  virtual const std::vector<Source>& GetSources() const = 0;
+ 
+   virtual content::DesktopMediaID::Type GetMediaListType() const = 0;
+ };
+diff --git a/chrome/browser/media/webrtc/desktop_media_list_base.cc b/chrome/browser/media/webrtc/desktop_media_list_base.cc
+index 43dd95ef72f5..d4662708f649 100644
+--- a/chrome/browser/media/webrtc/desktop_media_list_base.cc
++++ b/chrome/browser/media/webrtc/desktop_media_list_base.cc
+@@ -18,6 +18,11 @@ DesktopMediaListBase::DesktopMediaListBase(base::TimeDelta update_period)
+ 
+ DesktopMediaListBase::~DesktopMediaListBase() {}
+ 
++void DesktopMediaListBase::AddObserver(DesktopMediaListObserver* observer) {
++  DCHECK(!observer_);
++  observer_ = observer;
++}
++
+ void DesktopMediaListBase::SetUpdatePeriod(base::TimeDelta period) {
+   DCHECK(!observer_);
+   update_period_ = period;
+@@ -31,10 +36,7 @@ void DesktopMediaListBase::SetViewDialogWindowId(DesktopMediaID dialog_id) {
+   view_dialog_id_ = dialog_id;
+ }
+ 
+-void DesktopMediaListBase::StartUpdating(DesktopMediaListObserver* observer) {
+-  DCHECK(!observer_);
+-
+-  observer_ = observer;
++void DesktopMediaListBase::StartUpdating() {
+   Refresh();
+ }
+ 
+@@ -49,6 +51,11 @@ const DesktopMediaList::Source& DesktopMediaListBase::GetSource(
+   return sources_[index];
+ }
+ 
++const std::vector<DesktopMediaList::Source>& DesktopMediaListBase::GetSources()
++    const {
++  return sources_;
++}
++
+ DesktopMediaID::Type DesktopMediaListBase::GetMediaListType() const {
+   return type_;
+ }
+@@ -60,6 +67,12 @@ DesktopMediaListBase::SourceDescription::SourceDescription(
+ 
+ void DesktopMediaListBase::UpdateSourcesList(
+     const std::vector<SourceDescription>& new_sources) {
++  // Notify observer when there was no new source captured.
++  if (new_sources.empty()) {
++    observer_->OnSourceUnchanged(this);
++    return;
++  }
++
+   typedef std::set<DesktopMediaID> SourceSet;
+   SourceSet new_source_set;
+   for (size_t i = 0; i < new_sources.size(); ++i) {
+@@ -132,6 +145,8 @@ void DesktopMediaListBase::UpdateSourceThumbnail(DesktopMediaID id,
+ }
+ 
+ void DesktopMediaListBase::ScheduleNextRefresh() {
++  if (!observer_->ShouldScheduleNextRefresh(this))
++    return;
+   BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
+                                  base::BindOnce(&DesktopMediaListBase::Refresh,
+                                                 weak_factory_.GetWeakPtr()),
+diff --git a/chrome/browser/media/webrtc/desktop_media_list_base.h b/chrome/browser/media/webrtc/desktop_media_list_base.h
+index 746df1210aa9..461e0edf8509 100644
+--- a/chrome/browser/media/webrtc/desktop_media_list_base.h
++++ b/chrome/browser/media/webrtc/desktop_media_list_base.h
+@@ -24,12 +24,14 @@ class DesktopMediaListBase : public DesktopMediaList {
+   ~DesktopMediaListBase() override;
+ 
+   // DesktopMediaList interface.
++  void AddObserver(DesktopMediaListObserver* observer) override;
+   void SetUpdatePeriod(base::TimeDelta period) override;
+   void SetThumbnailSize(const gfx::Size& thumbnail_size) override;
+   void SetViewDialogWindowId(content::DesktopMediaID dialog_id) override;
+-  void StartUpdating(DesktopMediaListObserver* observer) override;
++  void StartUpdating() override;
+   int GetSourceCount() const override;
+   const Source& GetSource(int index) const override;
++  const std::vector<Source>& GetSources() const override;
+   content::DesktopMediaID::Type GetMediaListType() const override;
+ 
+   static uint32_t GetImageHash(const gfx::Image& image);
+diff --git a/chrome/browser/media/webrtc/desktop_media_list_observer.h b/chrome/browser/media/webrtc/desktop_media_list_observer.h
+index 47401abc984e..ca6a527ffac8 100644
+--- a/chrome/browser/media/webrtc/desktop_media_list_observer.h
++++ b/chrome/browser/media/webrtc/desktop_media_list_observer.h
+@@ -18,6 +18,10 @@ class DesktopMediaListObserver {
+                              int new_index) = 0;
+   virtual void OnSourceNameChanged(DesktopMediaList* list, int index) = 0;
+   virtual void OnSourceThumbnailChanged(DesktopMediaList* list, int index) = 0;
++  virtual void OnSourceUnchanged(DesktopMediaList* list) = 0;
++  // Return value indicates whether the observer should continue listening
++  // for capture updates.
++  virtual bool ShouldScheduleNextRefresh(DesktopMediaList* list) = 0;
+ 
+  protected:
+   virtual ~DesktopMediaListObserver() {}
+diff --git a/chrome/browser/media/webrtc/native_desktop_media_list.cc b/chrome/browser/media/webrtc/native_desktop_media_list.cc
+index 0c9ba953cb3c..5a2d853aeeac 100644
+--- a/chrome/browser/media/webrtc/native_desktop_media_list.cc
++++ b/chrome/browser/media/webrtc/native_desktop_media_list.cc
+@@ -5,10 +5,16 @@
+ #include "chrome/browser/media/webrtc/native_desktop_media_list.h"
+ 
+ #include "base/hash.h"
++#include "base/single_thread_task_runner.h"
++#include "base/strings/string_number_conversions.h"
+ #include "base/strings/utf_string_conversions.h"
+ #include "base/task_scheduler/post_task.h"
++#include "base/threading/thread_restrictions.h"
++#include "build/build_config.h"
+ #include "chrome/browser/media/webrtc/desktop_media_list_observer.h"
++#if 0
+ #include "chrome/grit/generated_resources.h"
++#endif
+ #include "content/public/browser/browser_thread.h"
+ #include "media/base/video_util.h"
+ #include "third_party/libyuv/include/libyuv/scale_argb.h"
+@@ -76,11 +82,13 @@ gfx::ImageSkia ScaleDesktopFrame(std::unique_ptr<webrtc::DesktopFrame> frame,
+ class NativeDesktopMediaList::Worker
+     : public webrtc::DesktopCapturer::Callback {
+  public:
+-  Worker(base::WeakPtr<NativeDesktopMediaList> media_list,
++  Worker(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
++         base::WeakPtr<NativeDesktopMediaList> media_list,
+          DesktopMediaID::Type type,
+          std::unique_ptr<webrtc::DesktopCapturer> capturer);
+   ~Worker() override;
+ 
++  void Start();
+   void Refresh(const DesktopMediaID::Id& view_dialog_id);
+ 
+   void RefreshThumbnails(const std::vector<DesktopMediaID>& native_ids,
+@@ -93,6 +101,9 @@ class NativeDesktopMediaList::Worker
+   void OnCaptureResult(webrtc::DesktopCapturer::Result result,
+                        std::unique_ptr<webrtc::DesktopFrame> frame) override;
+ 
++  // Task runner used for capturing operations.
++  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
++
+   base::WeakPtr<NativeDesktopMediaList> media_list_;
+ 
+   DesktopMediaID::Type type_;
+@@ -106,17 +117,27 @@ class NativeDesktopMediaList::Worker
+ };
+ 
+ NativeDesktopMediaList::Worker::Worker(
++    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+     base::WeakPtr<NativeDesktopMediaList> media_list,
+     DesktopMediaID::Type type,
+     std::unique_ptr<webrtc::DesktopCapturer> capturer)
+-    : media_list_(media_list), type_(type), capturer_(std::move(capturer)) {
+-  capturer_->Start(this);
++    : task_runner_(task_runner),
++      media_list_(media_list),
++      type_(type),
++      capturer_(std::move(capturer)) {}
++
++NativeDesktopMediaList::Worker::~Worker() {
++  DCHECK(task_runner_->BelongsToCurrentThread());
+ }
+ 
+-NativeDesktopMediaList::Worker::~Worker() {}
++void NativeDesktopMediaList::Worker::Start() {
++  DCHECK(task_runner_->BelongsToCurrentThread());
++  capturer_->Start(this);
++}
+ 
+ void NativeDesktopMediaList::Worker::Refresh(
+     const DesktopMediaID::Id& view_dialog_id) {
++  DCHECK(task_runner_->BelongsToCurrentThread());
+   std::vector<SourceDescription> result;
+ 
+   webrtc::DesktopCapturer::SourceList sources;
+@@ -133,11 +154,8 @@ void NativeDesktopMediaList::Worker::Refresh(
+         // Just in case 'Screen' is inflected depending on the screen number,
+         // use plural formatter.
+         title = mutiple_sources
+-                    ? l10n_util::GetPluralStringFUTF16(
+-                          IDS_DESKTOP_MEDIA_PICKER_MULTIPLE_SCREEN_NAME,
+-                          static_cast<int>(i + 1))
+-                    : l10n_util::GetStringUTF16(
+-                          IDS_DESKTOP_MEDIA_PICKER_SINGLE_SCREEN_NAME);
++                    ? base::UTF8ToUTF16("Screen " + base::IntToString(i + 1))
++                    : base::UTF8ToUTF16("Entire screen");
+         break;
+ 
+       case DesktopMediaID::TYPE_WINDOW:
+@@ -163,6 +181,7 @@ void NativeDesktopMediaList::Worker::Refresh(
+ void NativeDesktopMediaList::Worker::RefreshThumbnails(
+     const std::vector<DesktopMediaID>& native_ids,
+     const gfx::Size& thumbnail_size) {
++  DCHECK(task_runner_->BelongsToCurrentThread());
+   ImageHashesMap new_image_hashes;
+ 
+   // Get a thumbnail for each native source.
+@@ -210,17 +229,30 @@ NativeDesktopMediaList::NativeDesktopMediaList(
+     std::unique_ptr<webrtc::DesktopCapturer> capturer)
+     : DesktopMediaListBase(base::TimeDelta::FromMilliseconds(
+           kDefaultNativeDesktopMediaListUpdatePeriod)),
++      thread_("DesktopMediaListCaptureThread"),
+       weak_factory_(this) {
+   type_ = type;
+-  capture_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
+-      {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
+ 
+-  worker_.reset(
+-      new Worker(weak_factory_.GetWeakPtr(), type, std::move(capturer)));
++#if defined(OS_WIN) || defined(OS_MACOSX)
++  // On Windows/OSX the thread must be a UI thread.
++  base::MessageLoop::Type thread_type = base::MessageLoop::TYPE_UI;
++#else
++  base::MessageLoop::Type thread_type = base::MessageLoop::TYPE_DEFAULT;
++#endif
++  thread_.StartWithOptions(base::Thread::Options(thread_type, 0));
++
++  worker_.reset(new Worker(thread_.task_runner(), weak_factory_.GetWeakPtr(),
++                           type, std::move(capturer)));
++
++  thread_.task_runner()->PostTask(
++      FROM_HERE,
++      base::BindOnce(&Worker::Start, base::Unretained(worker_.get())));
+ }
+ 
+ NativeDesktopMediaList::~NativeDesktopMediaList() {
+-  capture_task_runner_->DeleteSoon(FROM_HERE, worker_.release());
++  base::ThreadRestrictions::ScopedAllowIO allow_io;
++  thread_.task_runner()->DeleteSoon(FROM_HERE, worker_.release());
++  thread_.Stop();
+ }
+ 
+ void NativeDesktopMediaList::Refresh() {
+@@ -230,7 +262,7 @@ void NativeDesktopMediaList::Refresh() {
+   new_aura_thumbnail_hashes_.clear();
+ #endif
+ 
+-  capture_task_runner_->PostTask(
++  thread_.task_runner()->PostTask(
+       FROM_HERE,
+       base::BindOnce(&Worker::Refresh, base::Unretained(worker_.get()),
+                      view_dialog_id_.id));
+@@ -280,7 +312,7 @@ void NativeDesktopMediaList::RefreshForAuraWindows(
+ #if defined(USE_AURA)
+     pending_native_thumbnail_capture_ = true;
+ #endif
+-    capture_task_runner_->PostTask(
++    thread_.task_runner()->PostTask(
+         FROM_HERE, base::BindOnce(&Worker::RefreshThumbnails,
+                                   base::Unretained(worker_.get()), native_ids,
+                                   thumbnail_size_));
+diff --git a/chrome/browser/media/webrtc/native_desktop_media_list.h b/chrome/browser/media/webrtc/native_desktop_media_list.h
+index e6f0e17b05ee..75c9ca04ce48 100644
+--- a/chrome/browser/media/webrtc/native_desktop_media_list.h
++++ b/chrome/browser/media/webrtc/native_desktop_media_list.h
+@@ -8,7 +8,7 @@
+ #include <memory>
+ 
+ #include "base/memory/weak_ptr.h"
+-#include "base/sequenced_task_runner.h"
++#include "base/threading/thread.h"
+ #include "chrome/browser/media/webrtc/desktop_media_list_base.h"
+ #include "content/public/browser/desktop_media_id.h"
+ #include "ui/gfx/image/image.h"
+@@ -44,12 +44,7 @@ class NativeDesktopMediaList : public DesktopMediaListBase {
+                                gfx::Image image);
+ #endif
+ 
+-  // Task runner used for the |worker_|.
+-  scoped_refptr<base::SequencedTaskRunner> capture_task_runner_;
+-
+-  // An object that does all the work of getting list of sources on a background
+-  // thread (see |capture_task_runner_|). Destroyed on |capture_task_runner_|
+-  // after the model is destroyed.
++  base::Thread thread_;
+   std::unique_ptr<Worker> worker_;
+ 
+ #if defined(USE_AURA)

+ 0 - 8
patches/common/webrtc/.patches.yaml

@@ -1,13 +1,5 @@
 repo: src/third_party/webrtc
 patches:
--
-  author: null
-  file: webrtc-desktop_capturer_mac.patch
-  description: null
--
-  author: null
-  file: webrtc-rwlock_null.patch
-  description: null
 -
   author: Nitish Sakhawalkar <[email protected]>
   file: disable-warning-win.patch

+ 0 - 117
patches/common/webrtc/webrtc-desktop_capturer_mac.patch

@@ -1,117 +0,0 @@
-diff --git a/modules/desktop_capture/mac/screen_capturer_mac.mm b/modules/desktop_capture/mac/screen_capturer_mac.mm
-index df18777226..6a1e3da6ab 100644
---- a/modules/desktop_capture/mac/screen_capturer_mac.mm
-+++ b/modules/desktop_capture/mac/screen_capturer_mac.mm
-@@ -16,6 +16,7 @@
- #include "rtc_base/checks.h"
- #include "rtc_base/constructormagic.h"
- #include "rtc_base/logging.h"
-+#include "rtc_base/synchronization/rw_lock_wrapper.h"
- #include "rtc_base/timeutils.h"
- #include "sdk/objc/Framework/Classes/Common/scoped_cftyperef.h"
- 
-@@ -28,18 +29,31 @@ namespace webrtc {
- // destroy itself once it's done.
- class DisplayStreamManager {
-  public:
--  int GetUniqueId() { return ++unique_id_generator_; }
--  void DestroyStream(int unique_id) {
--    auto it = display_stream_wrappers_.find(unique_id);
--    RTC_CHECK(it != display_stream_wrappers_.end());
--    RTC_CHECK(!it->second.active);
--    CFRelease(it->second.stream);
--    display_stream_wrappers_.erase(it);
-+  DisplayStreamManager() : rw_lock_(RWLockWrapper::CreateRWLock()) {}
-+  RWLockWrapper* GetLock() {return rw_lock_.get();};
- 
--    if (ready_for_self_destruction_ && display_stream_wrappers_.empty()) delete this;
-+  int GetUniqueId() {
-+    WriteLockScoped scoped_display_stream_manager_lock(*rw_lock_);
-+    return ++unique_id_generator_;
-+  }
-+  void DestroyStream(int unique_id) {
-+    bool finalize;
-+    {
-+      WriteLockScoped scoped_display_stream_manager_lock(*rw_lock_);
-+      auto it = display_stream_wrappers_.find(unique_id);
-+      RTC_CHECK(it != display_stream_wrappers_.end());
-+      RTC_CHECK(!it->second.active);
-+      CFRelease(it->second.stream);
-+      display_stream_wrappers_.erase(it);
-+      finalize = ready_for_self_destruction_ && display_stream_wrappers_.empty();
-+    }
-+    if (finalize) {
-+      delete this;
-+    }
-   }
- 
-   void SaveStream(int unique_id, CGDisplayStreamRef stream) {
-+    WriteLockScoped scoped_display_stream_manager_lock(*rw_lock_);
-     RTC_CHECK(unique_id <= unique_id_generator_);
-     DisplayStreamWrapper wrapper;
-     wrapper.stream = stream;
-@@ -47,6 +61,7 @@ class DisplayStreamManager {
-   }
- 
-   void UnregisterActiveStreams() {
-+    WriteLockScoped scoped_display_stream_manager_lock(*rw_lock_);
-     for (auto& pair : display_stream_wrappers_) {
-       DisplayStreamWrapper& wrapper = pair.second;
-       if (wrapper.active) {
-@@ -61,12 +76,23 @@ class DisplayStreamManager {
-   void PrepareForSelfDestruction() {
-     ready_for_self_destruction_ = true;
- 
--    if (display_stream_wrappers_.empty()) delete this;
-+    bool finalize;
-+    {
-+      WriteLockScoped scoped_display_stream_manager_lock(*rw_lock_);
-+      ready_for_self_destruction_ = true;
-+      finalize = display_stream_wrappers_.empty();
-+    }
-+    if (finalize) {
-+      delete this;
-+    }
-   }
- 
-   // Once the DisplayStreamManager is ready for destruction, the
-   // ScreenCapturerMac is no longer present. Any updates should be ignored.
--  bool ShouldIgnoreUpdates() { return ready_for_self_destruction_; }
-+  // Note: not thread-safe! Acquire and release a lock manually.
-+  bool ShouldIgnoreUpdates() {
-+     return ready_for_self_destruction_;
-+  }
- 
-  private:
-   struct DisplayStreamWrapper {
-@@ -81,6 +107,7 @@ class DisplayStreamManager {
-   std::map<int, DisplayStreamWrapper> display_stream_wrappers_;
-   int unique_id_generator_ = 0;
-   bool ready_for_self_destruction_ = false;
-+  std::unique_ptr<RWLockWrapper> rw_lock_;
- };
- 
- namespace {
-@@ -507,8 +534,6 @@ bool ScreenCapturerMac::RegisterRefreshAndMoveHandlers() {
-         return;
-       }
- 
--      if (manager->ShouldIgnoreUpdates()) return;
--
-       // Only pay attention to frame updates.
-       if (status != kCGDisplayStreamFrameStatusFrameComplete) return;
- 
-@@ -518,7 +543,12 @@ bool ScreenCapturerMac::RegisterRefreshAndMoveHandlers() {
-       if (count != 0) {
-         // According to CGDisplayStream.h, it's safe to call
-         // CGDisplayStreamStop() from within the callback.
--        ScreenRefresh(count, rects, display_origin);
-+        manager->GetLock()->AcquireLockShared();
-+        bool screen_capturer_mac_invalidated = manager->ShouldIgnoreUpdates();
-+        if (!screen_capturer_mac_invalidated) {
-+          ScreenRefresh(count, rects, display_origin);
-+        }
-+        manager->GetLock()->ReleaseLockShared();
-       }
-     };
- 

+ 0 - 36
patches/common/webrtc/webrtc-rwlock_null.patch

@@ -1,36 +0,0 @@
-diff --git a/rtc_base/synchronization/rw_lock_wrapper.cc b/rtc_base/synchronization/rw_lock_wrapper.cc
-index c8cd17edb8..50c6e25ad9 100644
---- a/rtc_base/synchronization/rw_lock_wrapper.cc
-+++ b/rtc_base/synchronization/rw_lock_wrapper.cc
-@@ -11,6 +11,9 @@
- #include "rtc_base/synchronization/rw_lock_wrapper.h"
- 
- #include <assert.h>
-+#include <stdlib.h>
-+
-+#include "system_wrappers/include/sleep.h"
- 
- #if defined(_WIN32)
- #include "rtc_base/synchronization/rw_lock_win.h"
-@@ -21,11 +23,19 @@
- namespace webrtc {
- 
- RWLockWrapper* RWLockWrapper::CreateRWLock() {
-+  RWLockWrapper* rw_lock_ptr;
- #ifdef _WIN32
--  return RWLockWin::Create();
-+  rw_lock_ptr = RWLockWin::Create();
- #else
--  return RWLockPosix::Create();
-+  rw_lock_ptr = RWLockPosix::Create();
- #endif
-+  if (rw_lock_ptr != NULL) {
-+    return rw_lock_ptr;
-+  } else {
-+    int msec_wait = 10 + (rand() % 90);
-+    SleepMs(msec_wait);
-+    return CreateRWLock();
-+  }
- }
- 
- }  // namespace webrtc