- Electron version: 0.37.6
- Operating system: All platforms

If you call WebContents’s `executeJavaScript()` method after the main frame finishes loading, but while a subframe is loading, the JS will never get executed and the call will never complete (unless you navigate the main frame to some new page). The culprit is how the JS additions to `WebContents` choose to forward the call to the `WebFrame`: https://github.com/electron/electron/blob/master/lib/browser/api/web-contents.js#L119

`webContents.isLoading()` will be true when a subframe is loading even if the main frame is finished. In that case the JS additions wait for `did-finish-load` before sending the call off to the frame, but that never happens.

I _think_ Chromium’s `WebContents::IsLoadingToDifferentDocument` is the thing we actually want to check (instead of `WebContents::IsLoading`), but that’s not exposed in Electron’s WebContents API. Should it be? If not, we could track the `did-get-response-details` event to determine whether the main frame is loading. (We can’t use `did-start-loading` because that fires for sub-frames and there’s currently no way to differentiate [should there be?]).

On the other hand, is this check really about not running scripts while a page is loading, or is it just about making sure at least the first page has been loaded? (The `this.getURL()` check is what makes me wonder). If so, it would be better and simpler to just have a flag that says a page has been loaded, so any `executeJavaScript` call is now safe to forward along.

Many Nightmare users are hitting this issue in real-world cases (it’s particularly bad on pretty much any page with ads), e.g. https://github.com/segmentio/nightmare/issues/375

Simple Electron app test case:

``` js
var electron = require('electron');
var mainWindow = null;

electron.app.on('ready', function() {
  mainWindow = new electron.BrowserWindow({show: true});

  mainWindow.webContents.on('did-finish-load', function() {
    console.log('Main frame loaded.');

    setTimeout(() => {
      mainWindow.webContents.executeJavaScript(`
        var iframe = document.createElement('iframe');
        iframe.src = 'http://cnn.com';
        document.body.appendChild(iframe);
      `);
    }, 40);

    setTimeout(function execute() {
      console.log('Started executeJavaScript');
      mainWindow.webContents.executeJavaScript(
        'console.log("hello");',
        result => {
          console.log('...finished');
          setTimeout(execute, 25);
        });
    }, 25);
  });

  mainWindow.webContents.loadURL('http://example.com');
});
```

This logs:

```
Main frame loaded.
Started executeJavaScript
...finished
Started executeJavaScript
```

And just stops there, when you should get `...finished` again.

atom/browser/api/atom_api_web_contents.cc
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/context_menu_params.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/static_http_user_agent_settings.h"
#include "net/url_request/url_request_context.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/base/l10n/l10n_util.h"
#include "atom/common/node_includes.h"
namespace {
struct PrintSettings {
  bool silent;
  bool print_background;
};
void SetUserAgentInIO(scoped_refptr<net::URLRequestContextGetter> getter,
                      std::string accept_lang,
                      std::string user_agent) {
  getter->GetURLRequestContext()->set_http_user_agent_settings(
      new net::StaticHttpUserAgentSettings(
          net::HttpUtil::GenerateAcceptLanguageHeader(accept_lang),
          user_agent));
}
}  
namespace mate {
template<>
struct Converter<atom::SetSizeParams> {
  static bool FromV8(v8::Isolate* isolate,