2

This issue relates to Chromium/Node.js (Atom Electron, Node Webkit, etc) based apps and not Chrome browser based apps.

When debugging the boot code of a program that uses Chromium and Node.js, there is a significant delay between the time that Dev Tools is invoked and it actually starts up fully, including the ability to execute break points. This means that in order to debug boot logic of an app, which occurs immediately after Dev Tools is invoked, inserted or stored breakpoints don't fire for this boot code.

The only workaround I have found is to add an adhoc timeout using setTimeout(continueBootLogic(), <time>) to defer starting of my boot logic for a until after I assume that Dev Tools is fully loaded.

There is an existing event in Electron MainWindow.on('devtools-opened', function() {...}) fires when dev tools opens but before the break point engine has booted. Using this event gets me closer in time to the actual ready moment but I still need a crummy timeout to wait a bit more.

Has anybody found a way to precisely and elegantly detect when dev tools is ready to start detecting and executing break points in the code?

Having this would greatly help efforts to debug boot code in Electron and nw.js so I can spend more time playing around with new APIs.

Here is a sample Electron program:

package.json:

{
  "name"    : "DevToolsWait",
  "version" : "0.2.0",
  "main"    : "main.js"
}

main.js:

'use strict'
const electron = require('electron')

console.log('Electron version: '+process.versions['electron'])

electron.app.on('ready', ()=>{
  var bw = new electron.BrowserWindow({width: 800, height: 600});

  // Load renderer.html
  bw.loadURL('file://' + __dirname + '/renderer.html');

  // Open the devtools.
  bw.webContents.openDevTools();


  // Handle devtools opened event
  bw.webContents.on('devtools-opened', ()=>{
    console.log("devtools-opened event called!")
    setImmediate(()=>{
        console.log("dev tools is now open (not sure if breakpoints work yet)!")
        // Send IPC call to main process that devtools is open
        bw.webContents.send('devtools-opened');
    });
  });


});

index.html:

<!DOCTYPE html>
<html>
  <head>
    <title>DevToolsWait Test!</title>
  </head>
  <body>

    <script>
        // Set this to 0 to get no timeout. 100ms seems to work on Linux with 1.2.1
        // Had to set as long as 1000ms to get it to work with older versions
        const iWaitTimeout = 100

        const electron = require('electron');


        // listen for Dev Tools opening event
        // Still have to wait a bit for break point engine to run
        electron.ipcRenderer.on('devtools-opened', function(){
            console.log('devtools-opened ipc called')
            // Start main logic

            if(iWaitTimeout==0){
                console.log('booting without timeout')
                bootGUI()

            } else {
                console.log('booting with timeout')
                setTimeout(bootGUI, 100)

            }

        });

        // Renderer process bootstrap logic
        function bootGUI(){
            console.log('bootGUI called')

            // Inserting ad-hoc debugger call. This should fire no matter what
            debugger;

            // ... doing other stuff

            if(iWaitTimeout===0){
                window.document.body.innerHTML+="If you see this message before debugger command line stops the code in the DevTools, then it failed. DevTools loaded event fired before the debugger is ready to handle breakpoints :(<br><br> Otherwise, woohoo!"
            } else {
                window.document.body.innerHTML+="If you see this message before debugger breaks, Then the timeout test failed. Maybe you should tweak the timeout to be a little longer to allow dev tools debugger time to warm up. see line with setTimeout(...) in renderer.html"
            }

        }



    </script>
  </body>
</html> 

Put all files in the same folder and To run, have electron installed and run electron . in the same folder as package.json.

To tweak the tests, iWaitTimeout in renderer.html.

My work around logic sets timeout to 100 milliseconds. This can be squeezed on my system but its likely computer and load dependent. Pretty messy solution IMO.

Would be awesome to have an event fire like devtools-breakpoint-ready or something similar. The logic above can likely be optimized a bit. I just started using Electron last night. Same issue is with Node Webkit.

Timothy C. Quinn
  • 3,739
  • 1
  • 35
  • 47
  • Duplicate of a duplicate? http://stackoverflow.com/questions/16765287/how-to-check-if-chrome-dev-tools-are-opened If that works, I would just continuously call that method until it was true – cgatian Jul 09 '15 at 01:25
  • I was hoping there was something more elegant but that may just work. I will give it a go. – Timothy C. Quinn Jul 09 '15 at 02:05
  • Nope. Failed on `console.profiles.length` with "TypeError: Cannot read property 'length' of undefined". The methodology is sound though. – Timothy C. Quinn Jul 09 '15 at 02:13
  • I found that I could set the break point in the dev tools and press F5 to refresh and it would reload the page and hit my debug point. Must be embedded in the dev tools. Depending on what your app is doing on startup this may work for you. – Shawn Rakowski Jul 09 '15 at 02:47
  • Did not work for me either. My app is calling a function pageLoaded() without any timeouts or delays and no breakpoints or debugger calls stop even with hard refresh. The only way to get breakpoints to work is to defer pageLoaded() call with a timeout. – Timothy C. Quinn Jul 09 '15 at 03:01
  • Can you make a snippet on jsBin/jsFiddle so we can better understand the situation? – cgatian Jul 09 '15 at 11:57
  • @cgatian - I added an electron sample above. Issue does not occur with regular browser based apps as I see it. Its more of a atom/electron or node-webkit related issue. – Timothy C. Quinn Jul 09 '15 at 16:21
  • [Update] I found the shim code between Electron and DevTools on Github (atom/brightray/browser/inspectable_web_contents_impl.cc) Interestingly there is a comment: InspectableWebContentsImpl::ShowDevTools() // Show devtools only after it has done loading, this is to make sure the // SetIsDocked is called *BEFORE* ShowDevTools. .... Maybe the ShowDevTools is firing earlier than it should? I am going to dig into the Electron forums to see what the intended function is supposed to be... – Timothy C. Quinn Jul 17 '15 at 23:30
  • I created a [ticket](https://github.com/atom/brightray/issues/125) in atom/brightray project to see if I get any traction there – Timothy C. Quinn Jul 17 '15 at 23:51

1 Answers1

3

you can detect when dev tool is opened using this:

mainWindow = new BrowserWindow({ width: 1024, height: 768 });
mainWindow.loadURL('your url');
mainWindow.webContents.openDevTools();
mainWindow.webContents.on('devtools-opened', () => {
    setImmediate(() => {
        // do whatever you want to do after dev tool completely opened here
        mainWindow.focus();
    });
});
Besat
  • 1,428
  • 13
  • 27