Merge autoland to m-c, a=merge
authorPhil Ringnalda <philringnalda@gmail.com>
Sun, 06 Nov 2016 18:17:49 -0800
changeset 351364 f43363843981d821e3bfb7d533b56e0615c4368e
parent 351353 673b5327afe1d489c41f683c79c6e8ad22040526 (current diff)
parent 351363 dbbd4d6ee7ecd2fe1d98b01b78be3749bb0c4bc9 (diff)
child 351378 908557c762f798605a2f96e4c943791cbada1b50
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone52.0a1
Merge autoland to m-c, a=merge MozReview-Commit-ID: 1roXGJWQJkC
--- a/browser/components/extensions/ext-browserAction.js
+++ b/browser/components/extensions/ext-browserAction.js
@@ -191,16 +191,23 @@ BrowserAction.prototype = {
         if (event.button == 0) {
           // Begin pre-loading the browser for the popup, so it's more likely to
           // be ready by the time we get a complete click.
           let tab = window.gBrowser.selectedTab;
           let popupURL = this.getProperty(tab, "popup");
           let enabled = this.getProperty(tab, "enabled");
 
           if (popupURL && enabled) {
+            // Add permission for the active tab so it will exist for the popup.
+            // Store the tab to revoke the permission during clearPopup.
+            if (!this.pendingPopup && !this.tabManager.hasActiveTabPermission(tab)) {
+              this.tabManager.addActiveTabPermission(tab);
+              this.tabToRevokeDuringClearPopup = tab;
+            }
+
             this.pendingPopup = this.getPopup(window, popupURL);
             window.addEventListener("mouseup", this, true);
           } else {
             this.clearPopup();
           }
         }
         break;
 
@@ -254,16 +261,20 @@ BrowserAction.prototype = {
   },
 
   /**
    * Clears any pending pre-loaded popup and related timeouts.
    */
   clearPopup() {
     this.clearPopupTimeout();
     if (this.pendingPopup) {
+      if (this.tabToRevokeDuringClearPopup) {
+        this.tabManager.revokeActiveTabPermission(this.tabToRevokeDuringClearPopup);
+        this.tabToRevokeDuringClearPopup = null;
+      }
       this.pendingPopup.destroy();
       this.pendingPopup = null;
     }
   },
 
   /**
    * Clears any pending timeouts to clear stale, pre-loaded popups.
    */
--- a/browser/components/extensions/ext-utils.js
+++ b/browser/components/extensions/ext-utils.js
@@ -593,16 +593,20 @@ ExtensionTabManager.prototype = {
       // Note that, unlike Chrome, we don't currently clear this permission with
       // the tab navigates. If the inner window is revived from BFCache before
       // we've granted this permission to a new inner window, the extension
       // maintains its permissions for it.
       this.hasTabPermissionFor.set(tab, tab.linkedBrowser.innerWindowID);
     }
   },
 
+  revokeActiveTabPermission(tab = TabManager.activeTab) {
+    this.hasTabPermissionFor.delete(tab);
+  },
+
   // Returns true if the extension has the "activeTab" permission for this tab.
   // This is somewhat more permissive than the generic "tabs" permission, as
   // checked by |hasTabPermission|, in that it also allows programmatic script
   // injection without an explicit host permission.
   hasActiveTabPermission(tab) {
     // This check is redundant with addTabPermission, but cheap.
     if (this.extension.hasPermission("activeTab")) {
       return (this.hasTabPermissionFor.has(tab) &&
--- a/browser/components/extensions/test/browser/browser_ext_browserAction_popup.js
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_popup.js
@@ -4,19 +4,19 @@
 
 function getBrowserAction(extension) {
   const {GlobalManager, Management: {global: {browserActionFor}}} = Cu.import("resource://gre/modules/Extension.jsm", {});
 
   let ext = GlobalManager.extensionMap.get(extension.id);
   return browserActionFor(ext);
 }
 
+let scriptPage = url => `<html><head><meta charset="utf-8"><script src="${url}"></script></head><body>${url}</body></html>`;
+
 function* testInArea(area) {
-  let scriptPage = url => `<html><head><meta charset="utf-8"><script src="${url}"></script></head><body>${url}</body></html>`;
-
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "background": {
         "page": "data/background.html",
       },
       "browser_action": {
         "default_popup": "popup-a.html",
         "browser_style": true,
@@ -228,45 +228,53 @@ add_task(function* testBrowserActionInPa
 
 add_task(function* testBrowserActionClickCanceled() {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "browser_action": {
         "default_popup": "popup.html",
         "browser_style": true,
       },
+      "permissions": ["activeTab"],
     },
 
     files: {
       "popup.html": `<!DOCTYPE html><html><head><meta charset="utf-8"></head></html>`,
     },
   });
 
   yield extension.startup();
 
   const {GlobalManager, Management: {global: {browserActionFor}}} = Cu.import("resource://gre/modules/Extension.jsm", {});
 
   let ext = GlobalManager.extensionMap.get(extension.id);
   let browserAction = browserActionFor(ext);
 
   let widget = getBrowserActionWidget(extension).forWindow(window);
+  let tab = window.gBrowser.selectedTab;
 
   // Test canceled click.
   EventUtils.synthesizeMouseAtCenter(widget.node, {type: "mousedown", button: 0}, window);
 
   isnot(browserAction.pendingPopup, null, "Have pending popup");
   is(browserAction.pendingPopup.window, window, "Have pending popup for the correct window");
 
   is(browserAction.pendingPopupTimeout, null, "Have no pending popup timeout");
 
+  is(browserAction.tabToRevokeDuringClearPopup, tab, "Tab to revoke was saved");
+  is(browserAction.tabManager.hasActiveTabPermission(tab), true, "Active tab was granted permission");
+
   EventUtils.synthesizeMouseAtCenter(document.documentElement, {type: "mouseup", button: 0}, window);
 
   is(browserAction.pendingPopup, null, "Pending popup was cleared");
   is(browserAction.pendingPopupTimeout, null, "Have no pending popup timeout");
 
+  is(browserAction.tabToRevokeDuringClearPopup, null, "Tab to revoke was removed");
+  is(browserAction.tabManager.hasActiveTabPermission(tab), false, "Permission was revoked from tab");
+
   // Test completed click.
   EventUtils.synthesizeMouseAtCenter(widget.node, {type: "mousedown", button: 0}, window);
 
   isnot(browserAction.pendingPopup, null, "Have pending popup");
   is(browserAction.pendingPopup.window, window, "Have pending popup for the correct window");
 
   is(browserAction.pendingPopupTimeout, null, "Have no pending popup timeout");
 
@@ -357,8 +365,49 @@ add_task(function* testBrowserActionDisa
   is(browserAction.pendingPopupTimeout, null, "Have no pending popup timeout");
 
   // Give the popup a chance to load and trigger a failure, if it was
   // erroneously opened.
   yield new Promise(resolve => setTimeout(resolve, 250));
 
   yield extension.unload();
 });
+
+add_task(function* testBrowserActionTabPopulation() {
+  // Note: This test relates to https://bugzilla.mozilla.org/show_bug.cgi?id=1310019
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "browser_action": {
+        "default_popup": "popup.html",
+        "browser_style": true,
+      },
+      "permissions": ["activeTab"],
+    },
+
+    files: {
+      "popup.html": scriptPage("popup.js"),
+      "popup.js": function() {
+        browser.tabs.query({active: true, currentWindow: true}).then(tabs => {
+          browser.test.assertEq("mochitest index /",
+                                tabs[0].title,
+                                "Tab has the expected title on first click");
+          browser.test.sendMessage("tabTitle");
+        });
+      },
+    },
+  });
+
+  let win = yield BrowserTestUtils.openNewBrowserWindow();
+  yield BrowserTestUtils.loadURI(win.gBrowser.selectedBrowser, "http://example.com/");
+  yield BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
+
+  yield extension.startup();
+
+  let widget = getBrowserActionWidget(extension).forWindow(win);
+  EventUtils.synthesizeMouseAtCenter(widget.node, {type: "mousedown", button: 0}, win);
+
+  yield extension.awaitMessage("tabTitle");
+
+  EventUtils.synthesizeMouseAtCenter(widget.node, {type: "mouseup", button: 0}, win);
+
+  yield extension.unload();
+  yield BrowserTestUtils.closeWindow(win);
+});
--- a/browser/components/feeds/nsFeedSniffer.cpp
+++ b/browser/components/feeds/nsFeedSniffer.cpp
@@ -130,17 +130,17 @@ FindChar(char c, const char *begin, cons
  *
  * Determine if a substring is the "documentElement" in the document.
  *
  * All of our sniffed substrings: <rss, <feed, <rdf:RDF must be the "document"
  * element within the XML DOM, i.e. the root container element. Otherwise,
  * it's possible that someone embedded one of these tags inside a document of
  * another type, e.g. a HTML document, and we don't want to show the preview
  * page if the document isn't actually a feed.
- * 
+ *
  * @param   start
  *          The beginning of the data being sniffed
  * @param   end
  *          The end of the data being sniffed, right before the substring that
  *          was found.
  * @returns true if the found substring is the documentElement, false 
  *          otherwise.
  */
--- a/db/sqlite3/src/moz.build
+++ b/db/sqlite3/src/moz.build
@@ -28,28 +28,24 @@ SOURCES += [
 # -DSQLITE_ENABLE_FTS3=1 enables the full-text index module.
 # -DSQLITE_CORE=1 statically links that module into the SQLite library.
 # -DSQLITE_DEFAULT_PAGE_SIZE=32768 and SQLITE_MAX_DEFAULT_PAGE_SIZE=32768
 # increases the page size from 1k, see bug 416330.  It must be kept in sync with
 # the value of PREF_TS_PAGESIZE_DEFAULT in mozStorageService.cpp.  The value can
 # be overridden on a per-platform basis through the use of the PREF_TS_PAGESIZE
 # hidden preference.  If that preference is missing or invalid then this value
 # will be used.
-# -DSQLITE_MAX_SCHEMA_RETRY increases the times SQLite may try to reparse
-# statements when the schema changes. This is important when supporting lots of
-# concurrent connections, especially when they use shared cache.
 # Note: Be sure to update the configure.in checks when these change!
 for var in ('SQLITE_SECURE_DELETE', 'SQLITE_THREADSAFE', 'SQLITE_CORE',
             'SQLITE_ENABLE_FTS3', 'SQLITE_ENABLE_UNLOCK_NOTIFY',
             'SQLITE_ENABLE_DBSTAT_VTAB'):
     DEFINES[var] = 1
 
 DEFINES['SQLITE_DEFAULT_PAGE_SIZE'] = 32768
 DEFINES['SQLITE_MAX_DEFAULT_PAGE_SIZE'] = 32768
-DEFINES['SQLITE_MAX_SCHEMA_RETRY'] = 25
 
 # -DSQLITE_WIN32_GETVERSIONEX=0 avoids using deprecated functions.
 # SQLite will just assume we are running on NT kinds of Windows. That's fine
 # because we don't support Win9x.
 # -DSQLITE_ALLOW_URI_AUTHORITY=1 enables uri authorities. See bug 879133.
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     DEFINES['SQLITE_WIN32_GETVERSIONEX'] = 0
     DEFINES['SQLITE_ALLOW_URI_AUTHORITY'] = 1
--- a/dom/html/HTMLFieldSetElement.cpp
+++ b/dom/html/HTMLFieldSetElement.cpp
@@ -219,24 +219,18 @@ void
 HTMLFieldSetElement::AddElement(nsGenericHTMLFormElement* aElement)
 {
   mDependentElements.AppendElement(aElement);
 
   // If the element that we are adding aElement is a fieldset, then all the
   // invalid elements in aElement are also invalid elements of this.
   HTMLFieldSetElement* fieldSet = FromContent(aElement);
   if (fieldSet) {
-    if (fieldSet->mInvalidElementsCount > 0) {
-      // The order we call UpdateValidity and adjust mInvalidElementsCount is
-      // important. We need to first call UpdateValidity in case
-      // mInvalidElementsCount was 0 before the call and will be incremented to
-      // 1 and so we need to change state to invalid. After that is done, we
-      // are free to increment mInvalidElementsCount to the correct amount.
+    for (int32_t i = 0; i < fieldSet->mInvalidElementsCount; i++) {
       UpdateValidity(false);
-      mInvalidElementsCount += fieldSet->mInvalidElementsCount - 1;
     }
     return;
   }
 
   // We need to update the validity of the fieldset.
   nsCOMPtr<nsIConstraintValidation> cvElmt = do_QueryObject(aElement);
   if (cvElmt &&
       cvElmt->IsCandidateForConstraintValidation() && !cvElmt->IsValid()) {
@@ -267,22 +261,17 @@ void
 HTMLFieldSetElement::RemoveElement(nsGenericHTMLFormElement* aElement)
 {
   mDependentElements.RemoveElement(aElement);
 
   // If the element that we are removing aElement is a fieldset, then all the
   // invalid elements in aElement are also removed from this.
   HTMLFieldSetElement* fieldSet = FromContent(aElement);
   if (fieldSet) {
-    if (fieldSet->mInvalidElementsCount > 0) {
-      // The order we update mInvalidElementsCount and call UpdateValidity is
-      // important. We need to first decrement mInvalidElementsCount and then
-      // call UpdateValidity, in case mInvalidElementsCount hits 0 in the call
-      // of UpdateValidity and we have to change state to valid.
-      mInvalidElementsCount -= fieldSet->mInvalidElementsCount - 1;
+    for (int32_t i = 0; i < fieldSet->mInvalidElementsCount; i++) {
       UpdateValidity(true);
     }
     return;
   }
 
   // We need to update the validity of the fieldset.
   nsCOMPtr<nsIConstraintValidation> cvElmt = do_QueryObject(aElement);
   if (cvElmt &&
new file mode 100644
--- /dev/null
+++ b/dom/html/crashtests/1290904.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <fieldset id="outer">
+      <fieldset id="inner">
+      </fieldset>
+    </fieldset>
+  </body>
+</html>
+<script>
+function appendTextareaToFieldset(fieldset) {
+  var textarea = document.createElement("textarea");
+  textarea.setAttribute("required", "");
+  fieldset.appendChild(textarea);
+}
+
+var innerFieldset = document.getElementById('inner');
+var outerFieldset = document.getElementById('outer');
+
+var fieldset = document.createElement('fieldset');
+appendTextareaToFieldset(fieldset);
+appendTextareaToFieldset(fieldset);
+appendTextareaToFieldset(fieldset);
+appendTextareaToFieldset(fieldset);
+
+// Adding a fieldset to a nested fieldset.
+innerFieldset.appendChild(fieldset);
+appendTextareaToFieldset(fieldset);
+appendTextareaToFieldset(fieldset);
+// This triggers mInvalidElementsCount checks in outer fieldset.
+appendTextareaToFieldset(outerFieldset);
+
+// Removing a fieldset from a nested fieldset.
+innerFieldset.removeChild(fieldset);
+// This triggers mInvalidElementsCount checks in outer fieldset.
+appendTextareaToFieldset(outerFieldset);
+</script>
--- a/dom/html/crashtests/crashtests.list
+++ b/dom/html/crashtests/crashtests.list
@@ -71,9 +71,10 @@ load 903106.html
 load 916322-1.html
 load 916322-2.html
 load 1032654.html
 load 1141260.html
 load 1228876.html
 load 1230110.html
 load 1237633.html
 load 1281972-1.html
-load 1282894.html
\ No newline at end of file
+load 1282894.html
+load 1290904.html
\ No newline at end of file
--- a/dom/media/systemservices/CamerasChild.cpp
+++ b/dom/media/systemservices/CamerasChild.cpp
@@ -381,45 +381,51 @@ CamerasChild::RecvReplyGetCaptureCapabil
   return true;
 }
 
 int
 CamerasChild::GetCaptureDevice(CaptureEngine aCapEngine,
                                unsigned int list_number, char* device_nameUTF8,
                                const unsigned int device_nameUTF8Length,
                                char* unique_idUTF8,
-                               const unsigned int unique_idUTF8Length)
+                               const unsigned int unique_idUTF8Length,
+                               bool* scary)
 {
   LOG((__PRETTY_FUNCTION__));
   nsCOMPtr<nsIRunnable> runnable =
     media::NewRunnableFrom([this, aCapEngine, list_number]() -> nsresult {
       if (this->SendGetCaptureDevice(aCapEngine, list_number)) {
         return NS_OK;
       }
       return NS_ERROR_FAILURE;
     });
   LockAndDispatch<> dispatcher(this, __func__, runnable);
   if (dispatcher.Success()) {
     base::strlcpy(device_nameUTF8, mReplyDeviceName.get(), device_nameUTF8Length);
     base::strlcpy(unique_idUTF8, mReplyDeviceID.get(), unique_idUTF8Length);
+    if (scary) {
+      *scary = mReplyScary;
+    }
     LOG(("Got %s name %s id", device_nameUTF8, unique_idUTF8));
   }
   return dispatcher.ReturnValue();
 }
 
 bool
 CamerasChild::RecvReplyGetCaptureDevice(const nsCString& device_name,
-                                        const nsCString& device_id)
+                                        const nsCString& device_id,
+                                        const bool& scary)
 {
   LOG((__PRETTY_FUNCTION__));
   MonitorAutoLock monitor(mReplyMonitor);
   mReceivedReply = true;
   mReplySuccess = true;
   mReplyDeviceName = device_name;
   mReplyDeviceID = device_id;
+  mReplyScary = scary;
   monitor.Notify();
   return true;
 }
 
 int
 CamerasChild::AllocateCaptureDevice(CaptureEngine aCapEngine,
                                     const char* unique_idUTF8,
                                     const unsigned int unique_idUTF8Length,
--- a/dom/media/systemservices/CamerasChild.h
+++ b/dom/media/systemservices/CamerasChild.h
@@ -160,17 +160,18 @@ public:
   int SetFakeDeviceChangeEvents();
 
   // these are response messages to our outgoing requests
   virtual bool RecvReplyNumberOfCaptureDevices(const int&) override;
   virtual bool RecvReplyNumberOfCapabilities(const int&) override;
   virtual bool RecvReplyAllocateCaptureDevice(const int&) override;
   virtual bool RecvReplyGetCaptureCapability(const CaptureCapability& capability) override;
   virtual bool RecvReplyGetCaptureDevice(const nsCString& device_name,
-                                         const nsCString& device_id) override;
+                                         const nsCString& device_id,
+                                         const bool& scary) override;
   virtual bool RecvReplyFailure(void) override;
   virtual bool RecvReplySuccess(void) override;
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   // the webrtc.org ViECapture calls are mirrored here, but with access
   // to a specific PCameras instance to communicate over. These also
   // run on the MediaManager thread
   int NumberOfCaptureDevices(CaptureEngine aCapEngine);
@@ -190,17 +191,18 @@ public:
   int GetCaptureCapability(CaptureEngine aCapEngine,
                            const char* unique_idUTF8,
                            const unsigned int capability_number,
                            webrtc::CaptureCapability& capability);
   int GetCaptureDevice(CaptureEngine aCapEngine,
                        unsigned int list_number, char* device_nameUTF8,
                        const unsigned int device_nameUTF8Length,
                        char* unique_idUTF8,
-                       const unsigned int unique_idUTF8Length);
+                       const unsigned int unique_idUTF8Length,
+                       bool* scary = nullptr);
   void ShutdownAll();
   int EnsureInitialized(CaptureEngine aCapEngine);
 
   webrtc::ExternalRenderer* Callback(CaptureEngine aCapEngine, int capture_id);
 
 private:
   CamerasChild();
   ~CamerasChild();
@@ -234,14 +236,15 @@ private:
   // Async response valid?
   bool mReceivedReply;
   // Async responses data contents;
   bool mReplySuccess;
   int mReplyInteger;
   webrtc::CaptureCapability mReplyCapability;
   nsCString mReplyDeviceName;
   nsCString mReplyDeviceID;
+  bool mReplyScary;
 };
 
 } // namespace camera
 } // namespace mozilla
 
 #endif  // mozilla_CamerasChild_h
--- a/dom/media/systemservices/CamerasParent.cpp
+++ b/dom/media/systemservices/CamerasParent.cpp
@@ -16,16 +16,21 @@
 #include "mozilla/Preferences.h"
 #include "nsIPermissionManager.h"
 #include "nsThreadUtils.h"
 #include "nsXPCOM.h"
 #include "nsNetUtil.h"
 
 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
 
+#if defined(_WIN32)
+#include <process.h>
+#define getpid() _getpid()
+#endif
+
 #undef LOG
 #undef LOG_ENABLED
 mozilla::LazyLogModule gCamerasParentLog("CamerasParent");
 #define LOG(args) MOZ_LOG(gCamerasParentLog, mozilla::LogLevel::Debug, args)
 #define LOG_ENABLED() MOZ_LOG_TEST(gCamerasParentLog, mozilla::LogLevel::Debug)
 
 namespace mozilla {
 namespace camera {
@@ -675,41 +680,45 @@ CamerasParent::RecvGetCaptureDevice(cons
 
   RefPtr<CamerasParent> self(this);
   RefPtr<Runnable> webrtc_runnable =
     media::NewRunnableFrom([self, aCapEngine, aListNumber]() -> nsresult {
       char deviceName[MediaEngineSource::kMaxDeviceNameLength];
       char deviceUniqueId[MediaEngineSource::kMaxUniqueIdLength];
       nsCString name;
       nsCString uniqueId;
+      int devicePid = 0;
       int error = -1;
       if (self->EnsureInitialized(aCapEngine)) {
           error = self->mEngines[aCapEngine].mPtrViECapture->GetCaptureDevice(aListNumber,
                                                                               deviceName,
                                                                               sizeof(deviceName),
                                                                               deviceUniqueId,
-                                                                              sizeof(deviceUniqueId));
+                                                                              sizeof(deviceUniqueId),
+                                                                              &devicePid);
       }
       if (!error) {
         name.Assign(deviceName);
         uniqueId.Assign(deviceUniqueId);
       }
       RefPtr<nsIRunnable> ipc_runnable =
-        media::NewRunnableFrom([self, error, name, uniqueId]() -> nsresult {
+        media::NewRunnableFrom([self, error, name, uniqueId, devicePid]() {
           if (self->IsShuttingDown()) {
             return NS_ERROR_FAILURE;
           }
           if (error) {
             LOG(("GetCaptureDevice failed: %d", error));
             Unused << self->SendReplyFailure();
             return NS_ERROR_FAILURE;
           }
+          bool scary = (devicePid == getpid());
 
-          LOG(("Returning %s name %s id", name.get(), uniqueId.get()));
-          Unused << self->SendReplyGetCaptureDevice(name, uniqueId);
+          LOG(("Returning %s name %s id (pid = %d)%s", name.get(),
+               uniqueId.get(), devicePid, (scary? " (scary)" : "")));
+          Unused << self->SendReplyGetCaptureDevice(name, uniqueId, scary);
           return NS_OK;
         });
       self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
       return NS_OK;
     });
   DispatchToVideoCaptureThread(webrtc_runnable);
   return true;
 }
--- a/dom/media/systemservices/PCameras.ipdl
+++ b/dom/media/systemservices/PCameras.ipdl
@@ -31,17 +31,17 @@ child:
   async DeliverFrame(CaptureEngine capEngine, int cap_id,
                      Shmem buffer, size_t size, uint32_t time_stamp,
                      int64_t ntp_time, int64_t render_time);
   async DeviceChange();
   async ReplyNumberOfCaptureDevices(int numdev);
   async ReplyNumberOfCapabilities(int numdev);
   async ReplyAllocateCaptureDevice(int numdev);
   async ReplyGetCaptureCapability(CaptureCapability cap);
-  async ReplyGetCaptureDevice(nsCString device_name, nsCString device_id);
+  async ReplyGetCaptureDevice(nsCString device_name, nsCString device_id, bool scary);
   async ReplyFailure();
   async ReplySuccess();
   async __delete__();
 
 parent:
   async NumberOfCaptureDevices(CaptureEngine engine);
   async NumberOfCapabilities(CaptureEngine engine, nsCString deviceUniqueIdUTF8);
 
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -47,17 +47,17 @@ MediaEngineRemoteVideoSource::Init()
 {
   LOG((__PRETTY_FUNCTION__));
   char deviceName[kMaxDeviceNameLength];
   char uniqueId[kMaxUniqueIdLength];
   if (mozilla::camera::GetChildAndCall(
     &mozilla::camera::CamerasChild::GetCaptureDevice,
     mCapEngine, mCaptureIndex,
     deviceName, kMaxDeviceNameLength,
-    uniqueId, kMaxUniqueIdLength)) {
+    uniqueId, kMaxUniqueIdLength, nullptr)) {
     LOG(("Error initializing RemoteVideoSource (GetCaptureDevice)"));
     return;
   }
 
   SetName(NS_ConvertUTF8toUTF16(deviceName));
   SetUUID(uniqueId);
 
   mInitDone = true;
@@ -491,17 +491,17 @@ void MediaEngineRemoteVideoSource::Refre
   // Caller looked up this source by uniqueId, so it shouldn't change
   char deviceName[kMaxDeviceNameLength];
   char uniqueId[kMaxUniqueIdLength];
 
   if (mozilla::camera::GetChildAndCall(
     &mozilla::camera::CamerasChild::GetCaptureDevice,
     mCapEngine, aIndex,
     deviceName, sizeof(deviceName),
-    uniqueId, sizeof(uniqueId))) {
+    uniqueId, sizeof(uniqueId), nullptr)) {
     return;
   }
 
   SetName(NS_ConvertUTF8toUTF16(deviceName));
 #ifdef DEBUG
   MOZ_ASSERT(GetUUID().Equals(uniqueId));
 #endif
 }
--- a/dom/media/webrtc/MediaEngineWebRTC.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTC.cpp
@@ -194,46 +194,37 @@ MediaEngineWebRTC::EnumerateVideoDevices
   int num;
   num = mozilla::camera::GetChildAndCall(
     &mozilla::camera::CamerasChild::NumberOfCaptureDevices,
     capEngine);
 
   for (int i = 0; i < num; i++) {
     char deviceName[MediaEngineSource::kMaxDeviceNameLength];
     char uniqueId[MediaEngineSource::kMaxUniqueIdLength];
-    bool scaryWindow = false;
+    bool scarySource = false;
 
     // paranoia
     deviceName[0] = '\0';
     uniqueId[0] = '\0';
     int error;
 
     error =  mozilla::camera::GetChildAndCall(
       &mozilla::camera::CamerasChild::GetCaptureDevice,
       capEngine,
       i, deviceName,
       sizeof(deviceName), uniqueId,
-      sizeof(uniqueId));
+      sizeof(uniqueId),
+      &scarySource);
     if (error) {
       LOG(("camera:GetCaptureDevice: Failed %d", error ));
       continue;
     }
 #ifdef DEBUG
     LOG(("  Capture Device Index %d, Name %s", i, deviceName));
 
-    if (aMediaSource == dom::MediaSourceEnum::Window) {
-      // TODO: Detect firefox windows
-      //scaryWindow = true;
-    }
-
-    if (aMediaSource == dom::MediaSourceEnum::Application) {
-      // TODO: Detect firefox application windows
-      //scaryWindow = true;
-    }
-
     webrtc::CaptureCapability cap;
     int numCaps = mozilla::camera::GetChildAndCall(
       &mozilla::camera::CamerasChild::NumberOfCapabilities,
       capEngine,
       uniqueId);
     LOG(("Number of Capabilities %d", numCaps));
     for (int j = 0; j < numCaps; j++) {
       if (mozilla::camera::GetChildAndCall(
@@ -257,17 +248,17 @@ MediaEngineWebRTC::EnumerateVideoDevices
     RefPtr<MediaEngineVideoSource> vSource;
     NS_ConvertUTF8toUTF16 uuid(uniqueId);
     if (mVideoSources.Get(uuid, getter_AddRefs(vSource))) {
       // We've already seen this device, just refresh and append.
       static_cast<MediaEngineRemoteVideoSource*>(vSource.get())->Refresh(i);
       aVSources->AppendElement(vSource.get());
     } else {
       vSource = new MediaEngineRemoteVideoSource(i, capEngine, aMediaSource,
-                                                 scaryKind || scaryWindow);
+                                                 scaryKind || scarySource);
       mVideoSources.Put(uuid, vSource); // Hashtable takes ownership.
       aVSources->AppendElement(vSource);
     }
   }
 
   if (mHasTabVideoSource || dom::MediaSourceEnum::Browser == aMediaSource) {
     aVSources->AppendElement(new MediaEngineTabVideoSource());
   }
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_types.h
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_types.h
@@ -36,12 +36,16 @@ typedef intptr_t ScreenId;
 const ScreenId kFullDesktopScreenId = -1;
 
 const ScreenId kInvalidScreenId = -2;
 
 
 typedef intptr_t ProcessId;
 const ProcessId DesktopProcessId = 0;
 
+#ifdef XP_WIN
+typedef int pid_t;
+#endif
+
 }  // namespace webrtc
 
 #endif  // WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_TYPES_H_
 
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_device_info.cc
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_device_info.cc
@@ -29,16 +29,17 @@ static inline void SetStringMember(char 
   buffer[nBufLen - 1] = '\0';
   *member = buffer;
 }
 
 DesktopDisplayDevice::DesktopDisplayDevice() {
   screenId_ = kInvalidScreenId;
   deviceUniqueIdUTF8_ = NULL;
   deviceNameUTF8_ = NULL;
+  pid_ = 0;
 }
 
 DesktopDisplayDevice::~DesktopDisplayDevice() {
   screenId_ = kInvalidScreenId;
 
   if (deviceUniqueIdUTF8_){
     delete [] deviceUniqueIdUTF8_;
   }
@@ -58,35 +59,44 @@ void DesktopDisplayDevice::setScreenId(c
 void DesktopDisplayDevice::setDeviceName(const char *deviceNameUTF8) {
   SetStringMember(&deviceNameUTF8_, deviceNameUTF8);
 }
 
 void DesktopDisplayDevice::setUniqueIdName(const char *deviceUniqueIdUTF8) {
   SetStringMember(&deviceUniqueIdUTF8_, deviceUniqueIdUTF8);
 }
 
+void DesktopDisplayDevice::setPid(const int pid) {
+  pid_ = pid;
+}
+
 ScreenId DesktopDisplayDevice::getScreenId() {
   return screenId_;
 }
 
 const char *DesktopDisplayDevice::getDeviceName() {
   return deviceNameUTF8_;
 }
 
 const char *DesktopDisplayDevice::getUniqueIdName() {
   return deviceUniqueIdUTF8_;
 }
 
+pid_t DesktopDisplayDevice::getPid() {
+  return pid_;
+}
+
 DesktopDisplayDevice& DesktopDisplayDevice::operator= (DesktopDisplayDevice& other) {
   if (&other == this) {
     return *this;
   }
   screenId_ = other.getScreenId();
   setUniqueIdName(other.getUniqueIdName());
   setDeviceName(other.getDeviceName());
+  pid_ = other.getPid();
 
   return *this;
 }
 
 
 DesktopApplication::DesktopApplication() {
   processId_ = 0;
   processPathNameUTF8_= NULL;
@@ -266,16 +276,17 @@ void DesktopDeviceInfoImpl::InitializeWi
     for (itr = list.begin(); itr != list.end(); itr++) {
       DesktopDisplayDevice *pWinDevice = new DesktopDisplayDevice;
       if (!pWinDevice) {
         continue;
       }
 
       pWinDevice->setScreenId(itr->id);
       pWinDevice->setDeviceName(itr->title.c_str());
+      pWinDevice->setPid(itr->pid);
 
       char idStr[BUFSIZ];
 #if WEBRTC_WIN
       _snprintf_s(idStr, sizeof(idStr), sizeof(idStr) - 1, "%ld", pWinDevice->getScreenId());
 #else
       snprintf(idStr, sizeof(idStr), "%ld", pWinDevice->getScreenId());
 #endif
       pWinDevice->setUniqueIdName(idStr);
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_device_info.h
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_device_info.h
@@ -13,27 +13,30 @@ namespace webrtc {
 class DesktopDisplayDevice {
 public:
   DesktopDisplayDevice();
   ~DesktopDisplayDevice();
 
   void setScreenId(const ScreenId screenId);
   void setDeviceName(const char *deviceNameUTF8);
   void setUniqueIdName(const char *deviceUniqueIdUTF8);
+  void setPid(pid_t pid);
 
   ScreenId getScreenId();
   const char *getDeviceName();
   const char *getUniqueIdName();
+  pid_t getPid();
 
   DesktopDisplayDevice& operator= (DesktopDisplayDevice& other);
 
 protected:
   ScreenId screenId_;
   char* deviceNameUTF8_;
   char* deviceUniqueIdUTF8_;
+  pid_t pid_;
 };
 
 typedef std::map<intptr_t,DesktopDisplayDevice*> DesktopDisplayDeviceList;
 
 class DesktopApplication {
 public:
   DesktopApplication();
   ~DesktopApplication();
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer.h
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer.h
@@ -24,16 +24,17 @@ namespace webrtc {
 class DesktopCaptureOptions;
 
 class WindowCapturer : public DesktopCapturer {
  public:
   typedef webrtc::WindowId WindowId;
 
   struct Window {
     WindowId id;
+    pid_t pid;
 
     // Title of the window in UTF-8 encoding.
     std::string title;
   };
 
   typedef std::vector<Window> WindowList;
 
   static WindowCapturer* Create(const DesktopCaptureOptions& options);
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_mac.mm
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_mac.mm
@@ -95,16 +95,18 @@ bool WindowCapturerMac::GetWindowList(Wi
   CFIndex count = CFArrayGetCount(window_array);
   for (CFIndex i = 0; i < count; ++i) {
     CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(
         CFArrayGetValueAtIndex(window_array, i));
     CFStringRef window_title = reinterpret_cast<CFStringRef>(
         CFDictionaryGetValue(window, kCGWindowName));
     CFNumberRef window_id = reinterpret_cast<CFNumberRef>(
         CFDictionaryGetValue(window, kCGWindowNumber));
+    CFNumberRef window_pid = reinterpret_cast<CFNumberRef>(
+        CFDictionaryGetValue(window, kCGWindowOwnerPID));
     CFNumberRef window_layer = reinterpret_cast<CFNumberRef>(
         CFDictionaryGetValue(window, kCGWindowLayer));
     if (window_title && window_id && window_layer) {
       //Skip windows of zero area
       CFDictionaryRef bounds_ref = reinterpret_cast<CFDictionaryRef>(
            CFDictionaryGetValue(window,kCGWindowBounds));
       CGRect bounds_rect;
       if(!(bounds_ref) ||
@@ -118,18 +120,21 @@ bool WindowCapturerMac::GetWindowList(Wi
       // Skip windows with layer=0 (menu, dock).
       int layer;
       CFNumberGetValue(window_layer, kCFNumberIntType, &layer);
       if (layer != 0)
         continue;
 
       int id;
       CFNumberGetValue(window_id, kCFNumberIntType, &id);
+      pid_t pid = 0;
+      CFNumberGetValue(window_pid, kCFNumberIntType, &pid);
       WindowCapturer::Window window;
       window.id = id;
+      window.pid = pid;
       if (!rtc::ToUtf8(window_title, &(window.title)) ||
           window.title.empty()) {
         continue;
       }
       windows->push_back(window);
     }
   }
 
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_win.cc
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_win.cc
@@ -56,16 +56,20 @@ BOOL CALLBACK WindowsEnumerationHandler(
       (wcscmp(class_name, L"ApplicationFrameWindow") == 0 ||
        wcscmp(class_name, L"Windows.UI.Core.CoreWindow") == 0)) {
     return TRUE;
   }
 
   WindowCapturer::Window window;
   window.id = reinterpret_cast<WindowCapturer::WindowId>(hwnd);
 
+  DWORD pid;
+  GetWindowThreadProcessId(hwnd, &pid);
+  window.pid = (pid_t)pid;
+
   const size_t kTitleLength = 500;
   WCHAR window_title[kTitleLength];
   // Truncate the title if it's longer than kTitleLength.
   GetWindowText(hwnd, window_title, kTitleLength);
   window.title = rtc::ToUtf8(window_title);
 
   // Skip windows when we failed to convert the title or it is empty.
   if (window.title.empty())
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.cc
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.cc
@@ -61,16 +61,19 @@ class WindowCapturerLinux : public Windo
   ::Window GetApplicationWindow(::Window window);
 
   // Returns true if the |window| is a desktop element.
   bool IsDesktopElement(::Window window);
 
   // Returns window title for the specified X |window|.
   bool GetWindowTitle(::Window window, std::string* title);
 
+  // Returns the id of the owning process.
+  int GetWindowProcessID(::Window window);
+
   Callback* callback_;
 
   scoped_refptr<SharedXDisplay> x_display_;
 
   Atom wm_state_atom_;
   Atom window_type_atom_;
   Atom normal_window_type_atom_;
   bool has_composite_extension_;
@@ -131,16 +134,19 @@ bool WindowCapturerLinux::GetWindowList(
     for (unsigned int i = 0; i < num_children; ++i) {
       // Iterate in reverse order to return windows from front to back.
       ::Window app_window =
           GetApplicationWindow(children[num_children - 1 - i]);
       if (app_window && !IsDesktopElement(app_window)) {
         Window w;
         w.id = app_window;
 
+        unsigned int processId = GetWindowProcessID(app_window);
+        w.pid = (pid_t)processId;
+
         XWindowAttributes window_attr;
         if(!XGetWindowAttributes(display(),w.id,&window_attr)){
           LOG(LS_ERROR)<<"Bad request for attributes for window ID:"<<w.id;
           continue;
         }
         if((window_attr.width <= 0) || (window_attr.height <=0)){
           continue;
         }
@@ -382,16 +388,24 @@ bool WindowCapturerLinux::GetWindowTitle
         XFreeStringList(list);
     }
     if (window_name.value)
       XFree(window_name.value);
   }
   return result;
 }
 
+int WindowCapturerLinux::GetWindowProcessID(::Window window) {
+  // Get _NET_WM_PID property of the window.
+  Atom process_atom = XInternAtom(display(), "_NET_WM_PID", True);
+  XWindowProperty<uint32_t> process_id(display(), window, process_atom);
+
+  return process_id.is_valid() ? *process_id.data() : 0;
+}
+
 }  // namespace
 
 // static
 WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) {
   if (!options.x_display())
     return NULL;
   return new WindowCapturerLinux(options);
 }
--- a/media/webrtc/trunk/webrtc/modules/video_capture/android/device_info_android.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/android/device_info_android.cc
@@ -226,17 +226,18 @@ uint32_t DeviceInfoAndroid::NumberOfDevi
 
 int32_t DeviceInfoAndroid::GetDeviceName(
     uint32_t deviceNumber,
     char* deviceNameUTF8,
     uint32_t deviceNameLength,
     char* deviceUniqueIdUTF8,
     uint32_t deviceUniqueIdUTF8Length,
     char* /*productUniqueIdUTF8*/,
-    uint32_t /*productUniqueIdUTF8Length*/) {
+    uint32_t /*productUniqueIdUTF8Length*/,
+    pid_t* /*pid*/) {
   if (deviceNumber >= g_camera_info->size())
     return -1;
   const AndroidCameraInfo& info = g_camera_info->at(deviceNumber);
   if (info.name.length() + 1 > deviceNameLength ||
       info.name.length() + 1 > deviceUniqueIdUTF8Length) {
     return -1;
   }
   memcpy(deviceNameUTF8, info.name.c_str(), info.name.length() + 1);
--- a/media/webrtc/trunk/webrtc/modules/video_capture/android/device_info_android.h
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/android/device_info_android.h
@@ -41,17 +41,18 @@ class DeviceInfoAndroid : public DeviceI
   virtual int32_t Refresh();
   virtual int32_t GetDeviceName(
       uint32_t deviceNumber,
       char* deviceNameUTF8,
       uint32_t deviceNameLength,
       char* deviceUniqueIdUTF8,
       uint32_t deviceUniqueIdUTF8Length,
       char* productUniqueIdUTF8 = 0,
-      uint32_t productUniqueIdUTF8Length = 0);
+      uint32_t productUniqueIdUTF8Length = 0,
+      pid_t* pid = 0);
   virtual int32_t CreateCapabilityMap(const char* deviceUniqueIdUTF8);
 
   virtual int32_t DisplayCaptureSettingsDialogBox(
       const char* /*deviceUniqueIdUTF8*/,
       const char* /*dialogTitleUTF8*/,
       void* /*parentWindow*/,
       uint32_t /*positionX*/,
       uint32_t /*positionY*/) { return -1; }
--- a/media/webrtc/trunk/webrtc/modules/video_capture/include/video_capture.h
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/include/video_capture.h
@@ -53,24 +53,26 @@ class VideoCaptureModule: public RefCoun
 
     // Returns the available capture devices.
     // deviceNumber   - Index of capture device.
     // deviceNameUTF8 - Friendly name of the capture device.
     // deviceUniqueIdUTF8 - Unique name of the capture device if it exist.
     //                      Otherwise same as deviceNameUTF8.
     // productUniqueIdUTF8 - Unique product id if it exist.
     //                       Null terminated otherwise.
+    // pid                 - Owning process id (pid).
     virtual int32_t GetDeviceName(
         uint32_t deviceNumber,
         char* deviceNameUTF8,
         uint32_t deviceNameLength,
         char* deviceUniqueIdUTF8,
         uint32_t deviceUniqueIdUTF8Length,
         char* productUniqueIdUTF8 = 0,
-        uint32_t productUniqueIdUTF8Length = 0) = 0;
+        uint32_t productUniqueIdUTF8Length = 0,
+        pid_t* pid = 0) = 0;
 
 
     // Returns the number of capabilities this device.
     virtual int32_t NumberOfCapabilities(
         const char* deviceUniqueIdUTF8) = 0;
 
     // Gets the capabilities of the named device.
     virtual int32_t GetCapability(
--- a/media/webrtc/trunk/webrtc/modules/video_capture/include/video_capture_defines.h
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/include/video_capture_defines.h
@@ -17,16 +17,20 @@
 
 namespace webrtc
 {
 // Defines
 #ifndef NULL
     #define NULL    0
 #endif
 
+#ifdef XP_WIN
+typedef int pid_t;
+#endif
+
 enum {kVideoCaptureUniqueNameLength =1024}; //Max unique capture device name lenght
 enum {kVideoCaptureDeviceNameLength =256}; //Max capture device name lenght
 enum {kVideoCaptureProductIdLength =128}; //Max product id length
 
 struct VideoCaptureCapability
 {
     int32_t width;
     int32_t height;
--- a/media/webrtc/trunk/webrtc/modules/video_capture/linux/device_info_linux.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/linux/device_info_linux.cc
@@ -222,17 +222,18 @@ uint32_t DeviceInfoLinux::NumberOfDevice
 
 int32_t DeviceInfoLinux::GetDeviceName(
                                          uint32_t deviceNumber,
                                          char* deviceNameUTF8,
                                          uint32_t deviceNameLength,
                                          char* deviceUniqueIdUTF8,
                                          uint32_t deviceUniqueIdUTF8Length,
                                          char* /*productUniqueIdUTF8*/,
-                                         uint32_t /*productUniqueIdUTF8Length*/)
+                                         uint32_t /*productUniqueIdUTF8Length*/,
+                                         pid_t* pid)
 {
     WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideoCapture, _id, "%s", __FUNCTION__);
 
     // Travel through /dev/video [0-63]
     uint32_t count = 0;
     char device[20];
     int fd = -1;
     bool found = false;
--- a/media/webrtc/trunk/webrtc/modules/video_capture/linux/device_info_linux.h
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/linux/device_info_linux.h
@@ -31,17 +31,18 @@ public:
     virtual uint32_t NumberOfDevices();
     virtual int32_t GetDeviceName(
         uint32_t deviceNumber,
         char* deviceNameUTF8,
         uint32_t deviceNameLength,
         char* deviceUniqueIdUTF8,
         uint32_t deviceUniqueIdUTF8Length,
         char* productUniqueIdUTF8=0,
-        uint32_t productUniqueIdUTF8Length=0);
+        uint32_t productUniqueIdUTF8Length=0,
+        pid_t* pid=0);
     /*
     * Fills the membervariable _captureCapabilities with capabilites for the given device name.
     */
     virtual int32_t CreateCapabilityMap (const char* deviceUniqueIdUTF8);
     virtual int32_t DisplayCaptureSettingsDialogBox(
         const char* /*deviceUniqueIdUTF8*/,
         const char* /*dialogTitleUTF8*/,
         void* /*parentWindow*/,
--- a/media/webrtc/trunk/webrtc/modules/video_capture/mac/avfoundation/video_capture_avfoundation_info.h
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/mac/avfoundation/video_capture_avfoundation_info.h
@@ -43,17 +43,18 @@ public:
      * productUniqueIdUTF8 - unique product id if it exist. Null terminated
      *      otherwise.
      */
     virtual int32_t GetDeviceName(
         uint32_t deviceNumber, char* deviceNameUTF8,
         uint32_t deviceNameLength, char* deviceUniqueIdUTF8,
         uint32_t deviceUniqueIdUTF8Length,
         char* productUniqueIdUTF8 = 0,
-        uint32_t productUniqueIdUTF8Length = 0);
+        uint32_t productUniqueIdUTF8Length = 0,
+        pid_t* pid = 0);
 
     /*
      *   Returns the number of capabilities for this device
      */
     virtual int32_t NumberOfCapabilities(
         const char* deviceUniqueIdUTF8);
 
     /*
--- a/media/webrtc/trunk/webrtc/modules/video_capture/mac/avfoundation/video_capture_avfoundation_info.mm
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/mac/avfoundation/video_capture_avfoundation_info.mm
@@ -49,17 +49,18 @@ uint32_t VideoCaptureMacAVFoundationInfo
     return captureDeviceCount;
 
 }
 
 int32_t VideoCaptureMacAVFoundationInfo::GetDeviceName(
     uint32_t deviceNumber, char* deviceNameUTF8,
     uint32_t deviceNameLength, char* deviceUniqueIdUTF8,
     uint32_t deviceUniqueIdUTF8Length, char* productUniqueIdUTF8,
-    uint32_t productUniqueIdUTF8Length)
+    uint32_t productUniqueIdUTF8Length,
+    pid_t* pid)
 {
     nsAutoreleasePool localPool;
     int errNum = [[_captureInfo getDeviceNamesFromIndex:deviceNumber
                    DefaultName:deviceNameUTF8 WithLength:deviceNameLength
                    AndUniqueID:deviceUniqueIdUTF8
                    WithLength:deviceUniqueIdUTF8Length
                    AndProductID:productUniqueIdUTF8
                    WithLength:productUniqueIdUTF8Length]intValue];
--- a/media/webrtc/trunk/webrtc/modules/video_capture/windows/device_info_ds.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/windows/device_info_ds.cc
@@ -174,46 +174,49 @@ int32_t DeviceInfoDS::Init()
                      "Failed to create CLSID_SystemDeviceEnum, error 0x%x", hr);
         return -1;
     }
     return 0;
 }
 uint32_t DeviceInfoDS::NumberOfDevices()
 {
     ReadLockScoped cs(_apiLock);
-    return GetDeviceInfo(0, 0, 0, 0, 0, 0, 0);
+    return GetDeviceInfo(0, 0, 0, 0, 0, 0, 0, 0);
 }
 
 int32_t DeviceInfoDS::GetDeviceName(
                                        uint32_t deviceNumber,
                                        char* deviceNameUTF8,
                                        uint32_t deviceNameLength,
                                        char* deviceUniqueIdUTF8,
                                        uint32_t deviceUniqueIdUTF8Length,
                                        char* productUniqueIdUTF8,
-                                       uint32_t productUniqueIdUTF8Length)
+                                       uint32_t productUniqueIdUTF8Length,
+                                       pid_t* pid)
 {
     ReadLockScoped cs(_apiLock);
     const int32_t result = GetDeviceInfo(deviceNumber, deviceNameUTF8,
                                          deviceNameLength,
                                          deviceUniqueIdUTF8,
                                          deviceUniqueIdUTF8Length,
                                          productUniqueIdUTF8,
-                                         productUniqueIdUTF8Length);
+                                         productUniqueIdUTF8Length,
+                                         pid);
     return result > (int32_t) deviceNumber ? 0 : -1;
 }
 
 int32_t DeviceInfoDS::GetDeviceInfo(
                                        uint32_t deviceNumber,
                                        char* deviceNameUTF8,
                                        uint32_t deviceNameLength,
                                        char* deviceUniqueIdUTF8,
                                        uint32_t deviceUniqueIdUTF8Length,
                                        char* productUniqueIdUTF8,
-                                       uint32_t productUniqueIdUTF8Length)
+                                       uint32_t productUniqueIdUTF8Length,
+                                       pid_t* pid)
 
 {
 
     // enumerate all video capture devices
     IEnumMoniker* _dsMonikerDevEnum = NULL;
     HRESULT hr =
         _dsDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
                                           &_dsMonikerDevEnum, 0);
--- a/media/webrtc/trunk/webrtc/modules/video_capture/windows/device_info_ds.h
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/windows/device_info_ds.h
@@ -51,17 +51,18 @@ public:
      */
     virtual int32_t
         GetDeviceName(uint32_t deviceNumber,
                       char* deviceNameUTF8,
                       uint32_t deviceNameLength,
                       char* deviceUniqueIdUTF8,
                       uint32_t deviceUniqueIdUTF8Length,
                       char* productUniqueIdUTF8,
-                      uint32_t productUniqueIdUTF8Length);
+                      uint32_t productUniqueIdUTF8Length,
+                      pid_t* pid);
 
     /*
      * Display OS /capture device specific settings dialog
      */
     virtual int32_t
         DisplayCaptureSettingsDialogBox(
                                         const char* deviceUniqueIdUTF8,
                                         const char* dialogTitleUTF8,
@@ -88,17 +89,18 @@ public:
 
 protected:
     int32_t GetDeviceInfo(uint32_t deviceNumber,
                           char* deviceNameUTF8,
                           uint32_t deviceNameLength,
                           char* deviceUniqueIdUTF8,
                           uint32_t deviceUniqueIdUTF8Length,
                           char* productUniqueIdUTF8,
-                          uint32_t productUniqueIdUTF8Length);
+                          uint32_t productUniqueIdUTF8Length,
+                          pid_t* pid);
 
     virtual int32_t
         CreateCapabilityMap(const char* deviceUniqueIdUTF8);
 private:
     ICreateDevEnum* _dsDevEnum;
     bool _CoUninitializeIsRequired;
     std::vector<VideoCaptureCapabilityWindows> _captureCapabilitiesWindows;
     HWND _hwnd;
--- a/media/webrtc/trunk/webrtc/video_engine/browser_capture_impl.h
+++ b/media/webrtc/trunk/webrtc/video_engine/browser_capture_impl.h
@@ -14,17 +14,18 @@ namespace webrtc {
     virtual int32_t Refresh() { return 0; }
 
     virtual int32_t GetDeviceName(uint32_t deviceNumber,
                                   char* deviceNameUTF8,
                                   uint32_t deviceNameLength,
                                   char* deviceUniqueIdUTF8,
                                   uint32_t deviceUniqueIdUTF8Length,
                                   char* productUniqueIdUTF8 = NULL,
-                                  uint32_t productUniqueIdUTF8Length = 0) {
+                                  uint32_t productUniqueIdUTF8Length = 0,
+                                  pid_t* pid = 0) {
       deviceNameUTF8 = const_cast<char*>(kDeviceName);
       deviceUniqueIdUTF8 = const_cast<char*>(kUniqueDeviceName);
       productUniqueIdUTF8 =  const_cast<char*>(kProductUniqueId);
       return 1;
     };
 
 
     virtual int32_t NumberOfCapabilities(const char* deviceUniqueIdUTF8) {
--- a/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.cc
@@ -53,17 +53,18 @@ uint32_t ScreenDeviceInfoImpl::NumberOfD
 }
 
 int32_t ScreenDeviceInfoImpl::GetDeviceName(uint32_t deviceNumber,
                                             char* deviceNameUTF8,
                                             uint32_t deviceNameUTF8Length,
                                             char* deviceUniqueIdUTF8,
                                             uint32_t deviceUniqueIdUTF8Length,
                                             char* productUniqueIdUTF8,
-                                            uint32_t productUniqueIdUTF8Length) {
+                                            uint32_t productUniqueIdUTF8Length,
+                                            pid_t* pid) {
 
   DesktopDisplayDevice desktopDisplayDevice;
 
   // always initialize output
   if (deviceNameUTF8 && deviceNameUTF8Length > 0) {
     memset(deviceNameUTF8, 0, deviceNameUTF8Length);
   }
 
@@ -149,17 +150,18 @@ uint32_t AppDeviceInfoImpl::NumberOfDevi
 }
 
 int32_t AppDeviceInfoImpl::GetDeviceName(uint32_t deviceNumber,
                                          char* deviceNameUTF8,
                                          uint32_t deviceNameUTF8Length,
                                          char* deviceUniqueIdUTF8,
                                          uint32_t deviceUniqueIdUTF8Length,
                                          char* productUniqueIdUTF8,
-                                         uint32_t productUniqueIdUTF8Length) {
+                                         uint32_t productUniqueIdUTF8Length,
+                                         pid_t* pid) {
 
   DesktopApplication desktopApplication;
 
   // always initialize output
   if (deviceNameUTF8Length && deviceNameUTF8Length > 0) {
     memset(deviceNameUTF8, 0, deviceNameUTF8Length);
   }
   if (deviceUniqueIdUTF8 && deviceUniqueIdUTF8Length > 0) {
@@ -180,16 +182,19 @@ int32_t AppDeviceInfoImpl::GetDeviceName
 
     const char *deviceUniqueId = desktopApplication.getUniqueIdName();
     len = deviceUniqueId ? strlen(deviceUniqueId) : 0;
     if (len && deviceUniqueIdUTF8 && len <= deviceUniqueIdUTF8Length) {
       memcpy(deviceUniqueIdUTF8,
              deviceUniqueId,
              len);
     }
+    if (pid) {
+      *pid = desktopApplication.getProcessId();
+    }
   }
   return 0;
 }
 
 int32_t AppDeviceInfoImpl::DisplayCaptureSettingsDialogBox(const char* deviceUniqueIdUTF8,
                                                            const char* dialogTitleUTF8,
                                                            void* parentWindow,
                                                            uint32_t positionX,
@@ -249,17 +254,18 @@ uint32_t WindowDeviceInfoImpl::NumberOfD
 }
 
 int32_t WindowDeviceInfoImpl::GetDeviceName(uint32_t deviceNumber,
                                             char* deviceNameUTF8,
                                             uint32_t deviceNameUTF8Length,
                                             char* deviceUniqueIdUTF8,
                                             uint32_t deviceUniqueIdUTF8Length,
                                             char* productUniqueIdUTF8,
-                                            uint32_t productUniqueIdUTF8Length) {
+                                            uint32_t productUniqueIdUTF8Length,
+                                            pid_t* pid) {
 
   DesktopDisplayDevice desktopDisplayDevice;
 
   // always initialize output
   if (deviceNameUTF8 && deviceNameUTF8Length > 0) {
     memset(deviceNameUTF8, 0, deviceNameUTF8Length);
   }
   if (deviceUniqueIdUTF8 && deviceUniqueIdUTF8Length > 0) {
@@ -284,16 +290,19 @@ int32_t WindowDeviceInfoImpl::GetDeviceN
 
     const char *deviceUniqueId = desktopDisplayDevice.getUniqueIdName();
     len = deviceUniqueId ? strlen(deviceUniqueId) : 0;
     if (len && deviceUniqueIdUTF8 && len <= deviceUniqueIdUTF8Length) {
       memcpy(deviceUniqueIdUTF8,
              deviceUniqueId,
              len);
     }
+    if (pid) {
+      *pid = desktopDisplayDevice.getPid();
+    }
   }
 
   return 0;
 }
 
 int32_t WindowDeviceInfoImpl::DisplayCaptureSettingsDialogBox(const char* deviceUniqueIdUTF8,
                                                               const char* dialogTitleUTF8,
                                                               void* parentWindow,
--- a/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.h
+++ b/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.h
@@ -50,17 +50,18 @@ public:
 
   virtual uint32_t NumberOfDevices();
   virtual int32_t GetDeviceName(uint32_t deviceNumber,
                                 char* deviceNameUTF8,
                                 uint32_t deviceNameLength,
                                 char* deviceUniqueIdUTF8,
                                 uint32_t deviceUniqueIdUTF8Length,
                                 char* productUniqueIdUTF8,
-                                uint32_t productUniqueIdUTF8Length);
+                                uint32_t productUniqueIdUTF8Length,
+                                pid_t* pid);
 
   virtual int32_t DisplayCaptureSettingsDialogBox(const char* deviceUniqueIdUTF8,
                                                   const char* dialogTitleUTF8,
                                                   void* parentWindow,
                                                   uint32_t positionX,
                                                   uint32_t positionY);
   virtual int32_t NumberOfCapabilities(const char* deviceUniqueIdUTF8);
   virtual int32_t GetCapability(const char* deviceUniqueIdUTF8,
@@ -88,17 +89,18 @@ public:
 
   virtual uint32_t NumberOfDevices();
   virtual int32_t GetDeviceName(uint32_t deviceNumber,
                                 char* deviceNameUTF8,
                                 uint32_t deviceNameLength,
                                 char* deviceUniqueIdUTF8,
                                 uint32_t deviceUniqueIdUTF8Length,
                                 char* productUniqueIdUTF8,
-                                uint32_t productUniqueIdUTF8Length);
+                                uint32_t productUniqueIdUTF8Length,
+                                pid_t* pid);
 
   virtual int32_t DisplayCaptureSettingsDialogBox(const char* deviceUniqueIdUTF8,
                                                   const char* dialogTitleUTF8,
                                                   void* parentWindow,
                                                   uint32_t positionX,
                                                   uint32_t positionY);
   virtual int32_t NumberOfCapabilities(const char* deviceUniqueIdUTF8);
   virtual int32_t GetCapability(const char* deviceUniqueIdUTF8,
@@ -125,17 +127,18 @@ public:
 
   virtual uint32_t NumberOfDevices();
   virtual int32_t GetDeviceName(uint32_t deviceNumber,
                                 char* deviceNameUTF8,
                                 uint32_t deviceNameLength,
                                 char* deviceUniqueIdUTF8,
                                 uint32_t deviceUniqueIdUTF8Length,
                                 char* productUniqueIdUTF8,
-                                uint32_t productUniqueIdUTF8Length);
+                                uint32_t productUniqueIdUTF8Length,
+                                pid_t* pid);
 
   virtual int32_t DisplayCaptureSettingsDialogBox(const char* deviceUniqueIdUTF8,
                                                   const char* dialogTitleUTF8,
                                                   void* parentWindow,
                                                   uint32_t positionX,
                                                   uint32_t positionY);
   virtual int32_t NumberOfCapabilities(const char* deviceUniqueIdUTF8);
   virtual int32_t GetCapability(const char* deviceUniqueIdUTF8,
--- a/media/webrtc/trunk/webrtc/video_engine/include/vie_capture.h
+++ b/media/webrtc/trunk/webrtc/video_engine/include/vie_capture.h
@@ -17,16 +17,20 @@
 
 #ifndef WEBRTC_VIDEO_ENGINE_INCLUDE_VIE_CAPTURE_H_
 #define WEBRTC_VIDEO_ENGINE_INCLUDE_VIE_CAPTURE_H_
 
 #include "webrtc/common_types.h"
 #include "webrtc/common_video/interface/i420_video_frame.h"
 #include "webrtc/common_video/rotation.h"
 
+#ifdef XP_WIN
+typedef int pid_t;
+#endif
+
 namespace webrtc {
 
 class VideoEngine;
 class VideoCaptureModule;
 
 // The observer is registered using RegisterInputObserver() and
 // deregistered using DeregisterInputObserver().
 class WEBRTC_DLLEXPORT ViEInputObserver {
@@ -141,17 +145,18 @@ class WEBRTC_DLLEXPORT ViECapture {
   // Gets the number of available capture devices.
   virtual int NumberOfCaptureDevices() = 0;
 
   // Gets the name and unique id of a capture device.
   virtual int GetCaptureDevice(unsigned int list_number,
                                char* device_nameUTF8,
                                const unsigned int device_nameUTF8Length,
                                char* unique_idUTF8,
-                               const unsigned int unique_idUTF8Length) = 0;
+                               const unsigned int unique_idUTF8Length,
+                               pid_t* pid = nullptr) = 0;
 
   // Allocates a capture device to be used in VideoEngine.
   virtual int AllocateCaptureDevice(const char* unique_idUTF8,
                                     const unsigned int unique_idUTF8Length,
                                     int& capture_id) = 0;
 
   // Registers an external capture device to be used in VideoEngine
   virtual int AllocateExternalCaptureDevice(
--- a/media/webrtc/trunk/webrtc/video_engine/vie_capture_impl.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_capture_impl.cc
@@ -64,21 +64,22 @@ int ViECaptureImpl::NumberOfCaptureDevic
   return  shared_data_->input_manager()->NumberOfCaptureDevices();
 }
 
 
 int ViECaptureImpl::GetCaptureDevice(unsigned int list_number,
                                      char* device_nameUTF8,
                                      unsigned int device_nameUTF8Length,
                                      char* unique_idUTF8,
-                                     unsigned int unique_idUTF8Length) {
+                                     unsigned int unique_idUTF8Length,
+                                     pid_t* pid) {
   return shared_data_->input_manager()->GetDeviceName(
       list_number,
       device_nameUTF8, device_nameUTF8Length,
-      unique_idUTF8, unique_idUTF8Length);
+      unique_idUTF8, unique_idUTF8Length, pid);
 }
 
 int ViECaptureImpl::AllocateCaptureDevice(
   const char* unique_idUTF8,
   const unsigned int unique_idUTF8Length,
   int& capture_id) {
   LOG(LS_INFO) << "AllocateCaptureDevice " << unique_idUTF8;
   const int32_t result =
--- a/media/webrtc/trunk/webrtc/video_engine/vie_capture_impl.h
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_capture_impl.h
@@ -25,17 +25,19 @@ class ViECaptureImpl
       public ViERefCount {
  public:
   // Implements ViECapture.
   virtual int Release();
   virtual int NumberOfCaptureDevices();
   virtual int GetCaptureDevice(unsigned int list_number, char* device_nameUTF8,
                                const unsigned int device_nameUTF8Length,
                                char* unique_idUTF8,
-                               const unsigned int unique_idUTF8Length);
+                               const unsigned int unique_idUTF8Length,
+                               pid_t* pid = nullptr);
+
   virtual int AllocateCaptureDevice(const char* unique_idUTF8,
                                     const unsigned int unique_idUTF8Length,
                                     int& capture_id);
   virtual int AllocateCaptureDevice(
       VideoCaptureModule& capture_module, int& capture_id);  // NOLINT
   virtual int AllocateExternalCaptureDevice(
       int& capture_id, ViEExternalCapture *&external_capture);
   virtual int ReleaseCaptureDevice(const int capture_id);
--- a/media/webrtc/trunk/webrtc/video_engine/vie_input_manager.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_input_manager.cc
@@ -65,24 +65,26 @@ int ViEInputManager::NumberOfCaptureDevi
   capture_device_info_->Refresh();
   return capture_device_info_->NumberOfDevices();
 }
 
 int ViEInputManager::GetDeviceName(uint32_t device_number,
                                    char* device_nameUTF8,
                                    uint32_t device_name_length,
                                    char* device_unique_idUTF8,
-                                   uint32_t device_unique_idUTF8Length) {
+                                   uint32_t device_unique_idUTF8Length,
+                                   pid_t* pid) {
   CriticalSectionScoped cs(device_info_cs_.get());
   GetDeviceInfo();
   assert(capture_device_info_);
   return capture_device_info_->GetDeviceName(device_number, device_nameUTF8,
                                              device_name_length,
                                              device_unique_idUTF8,
-                                             device_unique_idUTF8Length);
+                                             device_unique_idUTF8Length,
+                                             NULL, 0, pid);
 }
 
 int ViEInputManager::NumberOfCaptureCapabilities(
   const char* device_unique_idUTF8) {
   CriticalSectionScoped cs(device_info_cs_.get());
   if (!GetDeviceInfo())
     return 0;
   assert(capture_device_info_);
--- a/media/webrtc/trunk/webrtc/video_engine/vie_input_manager.h
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_input_manager.h
@@ -44,17 +44,18 @@ class ViEInputManager : private ViEManag
   // Returns number of capture devices.
   int NumberOfCaptureDevices();
 
   // Gets name and id for a capture device.
   int GetDeviceName(uint32_t device_number,
                     char* device_nameUTF8,
                     uint32_t device_name_length,
                     char* device_unique_idUTF8,
-                    uint32_t device_unique_idUTF8Length);
+                    uint32_t device_unique_idUTF8Length,
+                    pid_t* pid);
 
   // Returns the number of capture capabilities for a specified device.
   int NumberOfCaptureCapabilities(const char* device_unique_idUTF8);
 
   // Gets a specific capability for a capture device.
   int GetCaptureCapability(const char* device_unique_idUTF8,
                            const uint32_t device_capability_number,
                            CaptureCapability& capability);