Browse Source

feat: Add isCurrentlyAudible() to WebContents (#13614)

* :wrench: Add isCurrentlyAudible() to WebContents

* :heart: Implement feedback, use await to wait for event

* :construction_worker: Add missing imports
Felix Rieseberg 6 years ago
parent
commit
deedf6c3f4

+ 5 - 0
atom/browser/api/atom_api_web_contents.cc

@@ -1434,6 +1434,10 @@ bool WebContents::IsAudioMuted() {
   return web_contents()->IsAudioMuted();
 }
 
+bool WebContents::IsCurrentlyAudible() {
+  return web_contents()->IsCurrentlyAudible();
+}
+
 void WebContents::Print(mate::Arguments* args) {
   PrintSettings settings = {false, false, base::string16()};
   if (args->Length() >= 1 && !args->GetNext(&settings)) {
@@ -2018,6 +2022,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
       .SetMethod("setIgnoreMenuShortcuts", &WebContents::SetIgnoreMenuShortcuts)
       .SetMethod("setAudioMuted", &WebContents::SetAudioMuted)
       .SetMethod("isAudioMuted", &WebContents::IsAudioMuted)
+      .SetMethod("isCurrentlyAudible", &WebContents::IsCurrentlyAudible)
       .SetMethod("undo", &WebContents::Undo)
       .SetMethod("redo", &WebContents::Redo)
       .SetMethod("cut", &WebContents::Cut)

+ 1 - 0
atom/browser/api/atom_api_web_contents.h

@@ -143,6 +143,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
   void SetIgnoreMenuShortcuts(bool ignore);
   void SetAudioMuted(bool muted);
   bool IsAudioMuted();
+  bool IsCurrentlyAudible();
   void Print(mate::Arguments* args);
   std::vector<printing::PrinterBasicInfo> GetPrinterList();
   void SetEmbedder(const WebContents* embedder);

+ 4 - 0
docs/api/web-contents.md

@@ -832,6 +832,10 @@ Mute the audio on the current web page.
 
 Returns `Boolean` - Whether this page has been muted.
 
+#### `contents.isCurrentlyAudible()`
+
+Returns `Boolean` - Whether audio is currently playing.
+
 #### `contents.setZoomFactor(factor)`
 
 * `factor` Number - Zoom factor.

+ 4 - 0
docs/api/webview-tag.md

@@ -450,6 +450,10 @@ Set guest page muted.
 
 Returns `Boolean` - Whether guest page has been muted.
 
+#### `<webview>.isCurrentlyAudible()`
+
+Returns `Boolean` - Whether audio is currently playing.
+
 ### `<webview>.undo()`
 
 Executes editing command `undo` in page.

+ 1 - 0
lib/renderer/web-view/web-view.js

@@ -347,6 +347,7 @@ const registerWebViewElement = function () {
     'inspectElement',
     'setAudioMuted',
     'isAudioMuted',
+    'isCurrentlyAudible',
     'undo',
     'redo',
     'cut',

+ 21 - 0
spec/api-web-contents-spec.js

@@ -4,12 +4,18 @@ const assert = require('assert')
 const http = require('http')
 const path = require('path')
 const {closeWindow} = require('./window-helpers')
+const {emittedOnce} = require('./events-helpers')
+const chai = require('chai')
+const dirtyChai = require('dirty-chai')
 
 const {ipcRenderer, remote} = require('electron')
 const {BrowserWindow, webContents, ipcMain, session} = remote
+const {expect} = chai
 
 const isCi = remote.getGlobal('isCi')
 
+chai.use(dirtyChai)
+
 /* The whole webContents API doesn't use standard callbacks */
 /* eslint-disable standard/no-callback-literal */
 
@@ -116,6 +122,21 @@ describe('webContents module', () => {
     })
   })
 
+  describe('isCurrentlyAudible() API', () => {
+    it('returns whether audio is playing', async () => {
+      w.loadURL(`file://${path.join(__dirname, 'fixtures', 'api', 'is-currently-audible.html')}`)
+      w.show()
+      await emittedOnce(w.webContents, 'did-finish-load')
+
+      expect(w.webContents.isCurrentlyAudible()).to.be.false()
+
+      w.webContents.send('play')
+      await emittedOnce(ipcMain, 'playing')
+
+      expect(w.webContents.isCurrentlyAudible()).to.be.true()
+    })
+  })
+
   describe('getWebPreferences() API', () => {
     it('should not crash when called for devTools webContents', (done) => {
       w.webContents.openDevTools()

+ 21 - 0
spec/fixtures/api/is-currently-audible.html

@@ -0,0 +1,21 @@
+<html>
+<body>
+<div id="video"></div>
+<script type="text/javascript" charset="utf-8">
+  const {ipcRenderer} = window.top != null ? window.top.require('electron') : require('electron')
+  ipcRenderer.on('play', (event) => {
+    const context = new window.AudioContext();
+    const oscillator = context.createOscillator();
+
+    // A beep
+    oscillator.type = 'sine';
+    oscillator.frequency.value = 440
+    oscillator.connect(context.destination)
+    oscillator.start()
+
+    // It'll take a few ms before the beep shows up
+    setTimeout(() => event.sender.send('playing'), 100)
+  })
+</script>
+</body>
+</html>