Closed michaelcypher closed 4 years ago
I've run the same script while connecting to an Android and to a desktop browser and compared the the CDP messages that are sent and received. It looks like the Android browser returns different results to the desktop browser. My best guess is that either the Android or desktop browser is not correctly implementing the protocol (especially with regards to the Targets) function.
>>>
indicates an outbound request from my local machine to the browser
<<<
indicates an inbound request from the browser to my local machine
android_puppeteer node connect_to_android_browser.js
>>> { method: 'Target.getBrowserContexts', params: {}, id: 1 }
<<< {"id":1,"result":{"browserContextIds":[]}}
>>> { method: 'Target.setDiscoverTargets',
params: { discover: true },
id: 2 }
<<< {"method":"Target.targetCreated","params":{"targetInfo":{"targetId":"b2cf09a2-3937-40dc-824c-742d6cc994c3","type":"browser","title":"","url":"","attached":true}}}
<<< {"id":2,"result":{}}
>>> { method: 'Target.createTarget',
params: { url: 'about:blank', browserContextId: undefined },
id: 3 }
<<< {"method":"Target.targetCreated","params":{"targetInfo":{"targetId":"703A2642305F75EA9960B40A61AE4AC0","type":"page","title":"","url":"","attached":false,"browserContextId":"65CD42E50CA7A32F9166509B325A025E"}}}
<<< {"method":"Target.targetCreated","params":{"targetInfo":{"targetId":"64","type":"page","title":"","url":"about:blank","attached":false}}}
<<< {"id":3,"result":{"targetId":"64"}}
>>> { method: 'Target.attachToTarget',
params: { targetId: '64', flatten: true },
id: 4 }
<<< {"method":"Target.targetInfoChanged","params":{"targetInfo":{"targetId":"703A2642305F75EA9960B40A61AE4AC0","type":"page","title":"","url":"about:blank","attached":true,"browserContextId":"65CD42E50CA7A32F9166509B325A025E"}}}
<<< {"method":"Target.targetInfoChanged","params":{"targetInfo":{"targetId":"64","type":"page","title":"","url":"about:blank","attached":true}}}
<<< {"method":"Target.attachedToTarget","params":{"sessionId":"84D62166444AF2687591762176DEA70C","targetInfo":{"targetId":"64","type":"page","title":"","url":"about:blank","attached":true},"waitingForDebugger":false}}
<<< {"id":4,"result":{"sessionId":"84D62166444AF2687591762176DEA70C"}}
>>> { sessionId: '84D62166444AF2687591762176DEA70C',
method: 'Page.enable',
params: {},
id: 5 }
>>> { sessionId: '84D62166444AF2687591762176DEA70C',
method: 'Page.getFrameTree',
params: {},
id: 6 }
>>> { sessionId: '84D62166444AF2687591762176DEA70C',
method: 'Target.setAutoAttach',
params:
{ autoAttach: true,
waitForDebuggerOnStart: false,
flatten: true },
id: 7 }
>>> { sessionId: '84D62166444AF2687591762176DEA70C',
method: 'Performance.enable',
params: {},
id: 8 }
>>> { sessionId: '84D62166444AF2687591762176DEA70C',
method: 'Log.enable',
params: {},
id: 9 }
<<< {"method":"Target.targetInfoChanged","params":{"targetInfo":{"targetId":"703A2642305F75EA9960B40A61AE4AC0","type":"page","title":"about:blank","url":"about:blank","attached":true,"browserContextId":"65CD42E50CA7A32F9166509B325A025E"}}}
(hang)
android_puppeteer node connect_to_desktop_browser.js
>>> { method: 'Target.getBrowserContexts', params: {}, id: 1 }
<<< {"id":1,"result":{"browserContextIds":[]}}
>>> { method: 'Target.setDiscoverTargets',
params: { discover: true },
id: 2 }
<<< {"method":"Target.targetCreated","params":{"targetInfo":{"targetId":"28935A4E1B59610D302EF096FF9008BE","type":"page","title":"New Tab","url":"chrome://newtab/","attached":false,"browserContextId":"54B71F4416FC24B877FE5AD85E34B348"}}}
<<< {"method":"Target.targetCreated","params":{"targetInfo":{"targetId":"6dcd1d00-3aed-47b8-a7df-7ba814e4e7af","type":"browser","title":"","url":"","attached":true}}}
<<< {"id":2,"result":{}}
>>> { method: 'Target.createTarget',
params: { url: 'about:blank', browserContextId: undefined },
id: 3 }
<<< {"method":"Target.targetCreated","params":{"targetInfo":{"targetId":"E3791030F6661758C1C0B1C37A1AB747","type":"page","title":"","url":"about:blank","attached":false,"browserContextId":"54B71F4416FC24B877FE5AD85E34B348"}}}
<<< {"id":3,"result":{"targetId":"E3791030F6661758C1C0B1C37A1AB747"}}
>>> { method: 'Target.attachToTarget',
params:
{ targetId: 'E3791030F6661758C1C0B1C37A1AB747', flatten: true },
id: 4 }
<<< {"method":"Target.targetInfoChanged","params":{"targetInfo":{"targetId":"E3791030F6661758C1C0B1C37A1AB747","type":"page","title":"","url":"about:blank","attached":true,"browserContextId":"54B71F4416FC24B877FE5AD85E34B348"}}}
<<< {"method":"Target.attachedToTarget","params":{"sessionId":"4EFD88510A8FFC2FBED356CAE8A985CE","targetInfo":{"targetId":"E3791030F6661758C1C0B1C37A1AB747","type":"page","title":"","url":"about:blank","attached":true,"browserContextId":"54B71F4416FC24B877FE5AD85E34B348"},"waitingForDebugger":false}}
<<< {"id":4,"result":{"sessionId":"4EFD88510A8FFC2FBED356CAE8A985CE"}}
>>> { sessionId: '4EFD88510A8FFC2FBED356CAE8A985CE',
method: 'Page.enable',
params: {},
id: 5 }
>>> { sessionId: '4EFD88510A8FFC2FBED356CAE8A985CE',
method: 'Page.getFrameTree',
params: {},
id: 6 }
>>> { sessionId: '4EFD88510A8FFC2FBED356CAE8A985CE',
method: 'Target.setAutoAttach',
params:
{ autoAttach: true,
waitForDebuggerOnStart: false,
flatten: true },
id: 7 }
>>> { sessionId: '4EFD88510A8FFC2FBED356CAE8A985CE',
method: 'Performance.enable',
params: {},
id: 8 }
>>> { sessionId: '4EFD88510A8FFC2FBED356CAE8A985CE',
method: 'Log.enable',
params: {},
id: 9 }
<<< {"method":"Target.targetInfoChanged","params":{"targetInfo":{"targetId":"E3791030F6661758C1C0B1C37A1AB747","type":"page","title":"about:blank","url":"about:blank","attached":true,"browserContextId":"54B71F4416FC24B877FE5AD85E34B348"}}}
<<< {"id":5,"result":{}, "sessionId": "4EFD88510A8FFC2FBED356CAE8A985CE"}
...
Target.createTarget
method), the desktop browser sends one Target.targetCreated
message with a browserContextId
and correctly formatted targetId
(this is used in the result message), whereas the Android browser sends two Target.targetCreated
messages: the first with a browserContextId
and a targetId
that is formatted similar to the desktop browser message and the second without a browserContextId
and an integer targetId
that is not formatted similar to the desktop browser message (this is used in the result message. targetId
(i.e. the target that does not have a corresponding browserContextId
) for the Android browser. For the desktop browser, since there is only one created target, it connects to the target with the correctly formatted targetId
(which has a corresponding browserContextId
).Target.attachToTarget
method. For the desktop browser, the single created target has the info change to reflect that is has been attached to.My best guess is that the Android browser is incorrectly returning two targets when Puppeteer sends a message to create a target. The latter targetId
is incorrectly used as a result. Hope this helps and hope this indicates that there is a bug on Android Chrome (or at least a difference between Android Chrome and desktop Chrome).
I confirmed that the issue is due to the created target id (that is returned when puppeteer sends a Target.createTarget
method to Android Chrome) not having a corresponding browserContextId
. For example, if I use an already existing target with a browserContextId
, I can access the page just fine. This obviously only works if there is already an existing page in the browser, so this workaround is not permanent.
const puppeteer = require('puppeteer-core');
(async() => {
// Connect to Android Chrome browser
const browser = await puppeteer.connect({
browserWSEndpoint: 'ws://localhost:9222/devtools/browser',
});
// If a page already exists (with a browser context id), use it
const targets = await browser.targets().filter(
target => target._targetInfo.browserContextId != null);
// We don't have a way of creating a new target for Android Chrome due to the
// bug in https://github.com/ChromeDevTools/devtools-protocol/issues/180.
if (targets.length === 0) {
throw Error('no target exists with a browser context id');
}
// Use the first existing page
const target = targets[0];
const page = await target.page();
await page.goto('https://cypher.codes');
})();
This repository is related to Chrome DevTools Protocol, but does not track issues regarding its definition or implementation. If you want to file an issue for the Chrome DevTools Protocol, please open an issue on https://crbug.com under component: Platform>DevTools>Platform
. Thanks in advance!
Steps to reproduce
Starting Chrome on the Android device using adb:
Running this code using Node:
Current Behavior
When sending the
Page.enable
event to a Chrome instance running on Android via Puppeteer, the promise hangs and does not resolve. This occurs when executing thebrowser.newPage()
method. When executing this method, an empty new tab is opened on the mobile browser, but the method still hangs.Note:
Target.createTarget
does not hang and works as expected.Page.getFrameTree
also hangs.Expected Behavior
Page.enable
should not hang.Thanks.