88use Apix \Log \Logger \Stream as StreamLogger ;
99use HeadlessChromium \Browser \BrowserProcess ;
1010use HeadlessChromium \Browser \ProcessAwareBrowser ;
11+ use HeadlessChromium \Communication \Connection ;
12+ use HeadlessChromium \Exception \BrowserConnectionFailed ;
1113use Symfony \Component \Process \Process ;
14+ use Wrench \Exception \HandshakeException ;
1215
1316class BrowserFactory
1417{
@@ -37,9 +40,7 @@ public function __construct(string $chromeBinaries = null)
3740 * @param array $options options for browser creation:
3841 * - connectionDelay: amount of time in seconds to slows down connection for debugging purposes (default: none)
3942 * - customFlags: array of custom flag to flags to pass to the command line
40- * - debug: toggles the debug mode that allows to print additional details (default: false)
4143 * - debugLogger: resource string ("php://stdout"), resource or psr-3 logger instance (default: none)
42- * enabling debug logger will also enable debug mode.
4344 * - enableImages: toggle the loading of images (default: true)
4445 * - headless: whether chrome should be started headless (default: true)
4546 * - ignoreCertificateErrors: set chrome to ignore ssl errors
@@ -56,24 +57,13 @@ public function __construct(string $chromeBinaries = null)
5657 public function createBrowser (array $ options = []): ProcessAwareBrowser
5758 {
5859
59- // prepare logger
60- $ logger = $ options[ ' debugLogger ' ] ?? null ;
60+ // create logger from options
61+ $ logger = self :: createLogger ( $ options) ;
6162
62- // create logger from string name or resource
63- if (is_string ($ logger ) || is_resource ($ logger )) {
64- $ logger = new StreamLogger ($ logger );
65- $ options ['debug ' ] = true ;
66- }
67-
68- $ debugEnabled = $ options ['debug ' ] ?? false ;
69-
70- // log
71- if ($ debugEnabled ) {
63+ // log chrome version
64+ if ($ logger ) {
7265 $ chromeVersion = $ this ->getChromeVersion ();
73-
74- if ($ logger ) {
75- $ logger ->debug ('Factory: chrome version: ' . $ chromeVersion );
76- }
66+ $ logger ->debug ('Factory: chrome version: ' . $ chromeVersion );
7767 }
7868
7969 // create browser process
@@ -114,4 +104,76 @@ public function getChromeVersion()
114104
115105 return trim ($ process ->getOutput ());
116106 }
107+
108+ /**
109+ * Connects to an existing browser using it's web socket uri.
110+ *
111+ * usage:
112+ *
113+ * ```
114+ * $browserFactory = new BrowserFactory();
115+ * $browser = $browserFactory->createBrowser();
116+ *
117+ * $uri = $browser->getSocketUri();
118+ *
119+ * $existingBrowser = BrowserFactory::connectToBrowser($uri);
120+ * ```
121+ *
122+ * @param string $uri
123+ * @param array $options options when creating the connection to the browser:
124+ * - connectionDelay: amount of time in seconds to slows down connection for debugging purposes (default: none)
125+ * - debugLogger: resource string ("php://stdout"), resource or psr-3 logger instance (default: none)
126+ * - sendSyncDefaultTimeout: maximum time in ms to wait for synchronous messages to send (default 3000 ms)
127+ *
128+ * @return Browser
129+ * @throws BrowserConnectionFailed
130+ */
131+ public static function connectToBrowser (string $ uri , array $ options = []): Browser
132+ {
133+ $ logger = self ::createLogger ($ options );
134+
135+ if ($ logger ) {
136+ $ logger ->debug ('Browser Factory: connecting using ' . $ uri );
137+ }
138+
139+ // connect to browser
140+ $ connection = new Connection ($ uri , $ logger , $ options ['sendSyncDefaultTimeout ' ] ?? 3000 );
141+
142+ // try to connect
143+ try {
144+ $ connection ->connect ();
145+ } catch (HandshakeException $ e ) {
146+ throw new BrowserConnectionFailed ('Invalid socket uri ' , 0 , $ e );
147+ }
148+
149+ // make sure it is connected
150+ if (!$ connection ->isConnected ()) {
151+ throw new BrowserConnectionFailed ('Cannot connect to the browser, make sure it was not closed ' );
152+ }
153+
154+ // connection delay
155+ if (array_key_exists ('connectionDelay ' , $ options )) {
156+ $ connection ->setConnectionDelay ($ options ['connectionDelay ' ]);
157+ }
158+
159+ return new Browser ($ connection );
160+ }
161+
162+ /**
163+ * Create a logger instance from given options
164+ * @param $options
165+ * @return StreamLogger|null
166+ */
167+ private static function createLogger ($ options )
168+ {
169+ // prepare logger
170+ $ logger = $ options ['debugLogger ' ] ?? null ;
171+
172+ // create logger from string name or resource
173+ if (is_string ($ logger ) || is_resource ($ logger )) {
174+ $ logger = new StreamLogger ($ logger );
175+ }
176+
177+ return $ logger ;
178+ }
117179}
0 commit comments