Error: Tab does not support inspection with chrome remote interface

559 views
Skip to first unread message

Zack Chapple

unread,
Aug 2, 2016, 4:47:09 PM8/2/16
to headless-dev
I am trying to capture screenshots via node using the chrome-remote-interface package from Andrea Cardaci.  When I launch the app the first request generates the png as expected. However on the second request and all subsquent requests I get a error saying 

Error: Tab does not support inspection
     at /home/zack/Desktop/headless-snap/node_modules/chrome-remote-interface/lib/chrome.js:167:36
     at /home/zack/Desktop/headless-snap/node_modules/chrome-remote-interface/lib/devtools.js:47:13

Below is the code I am using to capture the screenshot and get my instance of Chrome.

app.post('/export', function (req, res) {
let startTime = Date.now();
let params = req.body;
if (!params.url) {
res.sendStatus(422)
}
Chrome(function (chromeInstance) {
chromeInstance.Page.loadEventFired(takeScreenshot.bind(null, chromeInstance, res, startTime));
chromeInstance.Page.enable();
chromeInstance.once('ready', ()=> {
chromeInstance.Page.navigate({url: params.url});
})
});

});

function takeScreenshot(instance, response, startTime) {
instance.Page.captureScreenshot().then((v) => {
let filename = `screenshot-${Date.now()}`;

let docEnd = Date.now();
fs.writeFileSync(filename + '.png', v.data, 'base64');
console.log(`Image saved as ${filename}.png`);
let imageEnd = Date.now();
console.log('image success in: ' + (+imageEnd - +startTime) + "ms");
});
}

Eric Seckler

unread,
Aug 3, 2016, 3:53:22 AM8/3/16
to Zack Chapple, headless-dev
I'm not familiar with chrome-remote-interface, but this sounds like you might be trying to connect two DevTools clients to the same tab? (DevTools currently only supports a single client per tab.)

--
You received this message because you are subscribed to the Google Groups "headless-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to headless-dev...@chromium.org.
To post to this group, send email to headle...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/headless-dev/6774e875-d192-4cf5-94f6-812544f7c0d3%40chromium.org.

els...@gmail.com

unread,
Feb 22, 2017, 8:12:01 PM2/22/17
to headless-dev, zackaryc...@gmail.com
Is it possible to have multiple tabs (and thus two clients) with one running headless_shell instance?

Jianzhou Feng

unread,
Feb 22, 2017, 11:10:10 PM2/22/17
to els...@gmail.com, headless-dev, zackaryc...@gmail.com
Maybe try adding
instance.close();
under 
console.log('image success in: ' + (+imageEnd - +startTime) + "ms");?

To unsubscribe from this group and stop receiving emails from it, send an email to headless-dev+unsubscribe@chromium.org.

To post to this group, send email to headle...@chromium.org.

Eric Seckler

unread,
Feb 23, 2017, 2:30:37 AM2/23/17
to els...@gmail.com, headless-dev, zackaryc...@gmail.com
On Thu, Feb 23, 2017, 01:12 <els...@gmail.com> wrote:
Is it possible to have multiple tabs (and thus two clients) with one running headless_shell instance?
Yes, you can open additional tabs (DevTools "targets") using the commands in the Target domain, e.g. Target.createTarget:


Once you've done that, you can connect one of your clients to the new target's DevTools endpoint as per usual.

Jan Potoms

unread,
Feb 23, 2017, 3:09:08 AM2/23/17
to headless-dev, els...@gmail.com, zackaryc...@gmail.com

els...@gmail.com

unread,
Feb 23, 2017, 1:08:10 PM2/23/17
to headless-dev, els...@gmail.com, zackaryc...@gmail.com
Thanks Jan - yeah, I came across your example and saw the Target object.. and maybe I'm close but not quite - I tried adapting your code to work with my other working example - do you see something obviously wrong here? I don't get an exception, but I'm guessing I previously working code incorrectly in a probably-obvious-to-you way. (Zackary might laugh when he sees this because it's an adaptation of his example code for PDFing screenshots.

What I'm trying to accomplish is to have a server that keeps the headless_shell (or chrome --headless) process alive while child processes connect to it to take screenshots of many URLs concurrently (in particular I'm trying to replace phantomjs in DPXDT - https://github.com/bslatkin/dpxdt)

Thanks

code:

var cri = require('chrome-remote-interface');
var tabManagerP;

let resourcesToIgnore = [
];

let viewportSize = {
  width: 480,
  height: 1000,
};
const outputPath = 'screenshot.png';


function getTabManager () {
  if (!tabManagerP) {
    tabManagerP = cri({ port: 9222 });
  }
  return tabManagerP;
}

function executeInTab(workFn) {
  return getTabManager()
    .then(tabManager => {
      return tabManager.Target.createTarget({ url: 'about:blank' })
        .then(({ targetId }) => {
          return cri.List({ port: 9222 })
            .then(list => {
              var url = list.find(target => target.id === targetId).webSocketDebuggerUrl;
              return cri({ tab: url });
            })
            .then(devtools => workFn(devtools))
            .then(result => {
              return tabManager.Target.closeTarget({ targetId })
                .then(() => result);
            }, error => {
              return tabManager.Target.closeTarget({ targetId })
                .then(() => {
                  throw error;
                });
            });
        });
    });
}

executeInTab(devtools => {
  return doSomethingWithDevtools(devtools);
}).then(result => {
  console.log(result);
});

function doSomethingWithDevtools(client) {
  console.log('doSomethingWithDevtools!!')
  const { Emulation, Network, Page } = client;

  Emulation.setVisibleSize({
    width: viewportSize.width,
    height: viewportSize.height,
  });

  if (resourcesToIgnore && resourcesToIgnore.length) {
    resourcesToIgnore.forEach(url => {
      console.log('× addBlockedURL', url);
      Network.addBlockedURL({
        url: url,
      });
    });
  }

  Network.requestWillBeSent(params => {
    const url = params.request.url;
    console.log(`-> ${params.requestId} ${url.substring(0, 150)}`);
  });

  Network.loadingFailed(params => {
    console.log('*** loadingFailed: ', params.requestId);
  });

  Network.loadingFinished(params => {
    console.log('<-', params.requestId, params.encodedDataLength);
  });

  Page.loadEventFired(
    () => {
      console.log('loadEventFired!');
      setTimeout(() => {
        Page.captureScreenshot().then(
          v => {
            console.log('writing screenshot to', outputPath);
            fs.writeFileSync(outputPath, v.data, 'base64');
            console.log(`Image saved as ${outputPath}`);
            client.close();
          }
        );
      }, 1000);
    }
  );

  return Promise.all([
    Network.enable(),
    Page.enable()
  ]).then(() => {
    return Page.navigate({ url: targetUrl });
  }).catch((err) => {
    console.error(`ERROR: ${err.message}`);
    client.close();
  });

els...@gmail.com

unread,
Feb 23, 2017, 1:45:30 PM2/23/17
to headless-dev, els...@gmail.com, zackaryc...@gmail.com
Yeah, doing some debugging this morning it looks like I'm just closing the tab prematurely and need to chain my promises differently (commenting out the closeTarget line leaves me with a screenshot)

Jan Potoms

unread,
Feb 23, 2017, 2:17:30 PM2/23/17
to headless-dev, els...@gmail.com, zackaryc...@gmail.com
Want to mention that in the meantime I adapted my own code as follows


function getTabManager () {
  if (!tabManagerP) {
    tabManagerP = new Promise((resolve, reject) => {
      const emitter = cri({ tab: `ws://localhost:${9222}/devtools/browser` }, resolve);
      emitter.once('disconnect', () => {
        tabManagerP = null;
        reject(new Error('Tabmanager disconnected'));
      });
      emitter.once('error', error => {
        tabManagerP = null;
        reject(error);
      });
    });
  }
  return tabManagerP;
}

This makes it renew the tabManager when the connection is lost.

Lindsey Simon

unread,
Feb 23, 2017, 3:04:31 PM2/23/17
to Jan Potoms, headless-dev, zackaryc...@gmail.com
OK, so this version works. If anyone has suggestions I'm totally open btw =)


var cri = require('chrome-remote-interface');
var tabManagerP;

let resourcesToIgnore = [
];

let viewportSize = {
  width: 480,
  height: 3000,
};
const outputPath = 'screenshot.png';


function getTabManager() {
  if (!tabManagerP) {
    tabManagerP = new Promise((resolve, reject) => {
      const emitter = cri({ tab: `ws://localhost:${9222}/devtools/browser` }, resolve);
      emitter.once('disconnect', () => {
        tabManagerP = null;
        reject(new Error('Tabmanager disconnected'));
      });
      emitter.once('error', error => {
        tabManagerP = null;
        reject(error);
      });
    });
  }
  return tabManagerP;
}

function executeInTab(workFn) {
  return getTabManager()
    .then(tabManager => {
      return tabManager.Target.createTarget({ url: 'about:blank' })
        .then(({ targetId }) => {
          return cri.List({ port: 9222 })
            .then(list => {
              var url = list.find(target => target.id === targetId).webSocketDebuggerUrl;
              return cri({ tab: url });
            })
            .then(devtools => workFn(devtools))
            .then(result => {
              console.log('closing tab with targetId', targetId)
              return tabManager.Target.closeTarget({ targetId })
                .then(() => result);
            }, error => {
              return tabManager.Target.closeTarget({ targetId })
                .then(() => {
                  throw error;
                });
            });
        });
    });
}

function doSomethingWithDevtools(client) {
  return new Promise((resolve, reject) => {
    const { Emulation, Network, Page } = client;
    console.log('doSomethingWithDevtools!!')
              resolve();
            }
          );
        }, 1000);
      }
    );

    Promise.all([
      Network.enable(),
      Page.enable()
    ]).then(() => {
      console.log('Page.navigate', targetUrl)
      Page.navigate({ url: targetUrl });
    }).catch((err) => {
      console.error(`ERROR: ${err.message}`);
      client.close();
      reject(err);
    });
  });
}

executeInTab(devtools => {
  return doSomethingWithDevtools(devtools);
}).then(result => {
  console.log('ALL DONE.');
  process.exit(0);
});

Reply all
Reply to author
Forward
0 new messages