Skip to content

Commit 7ce409b

Browse files
committed
Added BrowserFactory::connectToBrowser #42
1 parent 100b4cf commit 7ce409b

File tree

7 files changed

+123
-26
lines changed

7 files changed

+123
-26
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
* Features:
2121
* Added option ``keepAlive`` for browser factory.
2222
* Added methods ``BrowserProcess::getSocketUri`` and ``ProcessAwareBrowser::getSocketUri``
23+
* Removed unused option ``debug``
24+
* Added ``BrowserFactory::connectToBrowser``
2325
* Bug fixes:
2426
* none
2527

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ Here are the options available for the browser factory:
133133
|--------------------|---------------|--------------------------------------------------------------------------------------------------|
134134
| connectionDelay | 0 | Delay to apply between each operation for debugging purposes |
135135
| customFlags | none | Array of flags to pass to the command line. Eg: ``['--option1', '--option2=someValue']`` |
136-
| debug | false | Allows to enable debug mode |
137136
| debugLogger | null | A string (e.g "php://stdout"), or resource, or PSR-3 logger instance to print debug messages |
138137
| enableImages | true | Toggles loading of images |
139138
| headless | true | Enable or disable headless mode |

src/Browser.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ public function __construct(Connection $connection)
6868
->debug('✘ target(' . $params['targetId'] . ') was destroyed and unreferenced.');
6969
}
7070
});
71+
72+
// enable target discovery
73+
$connection->sendMessageSync(new Message('Target.setDiscoverTargets', ['discover' => true]));
7174
}
7275

7376
/**

src/Browser/BrowserProcess.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class BrowserProcess implements LoggerAwareInterface
7070

7171
/**
7272
* BrowserProcess constructor.
73-
* @param LoggerInterface $logger
73+
* @param LoggerInterface|null $logger
7474
*/
7575
public function __construct(LoggerInterface $logger = null)
7676
{
@@ -146,9 +146,6 @@ public function start($binaries, $options)
146146

147147
// create browser instance
148148
$this->browser = new ProcessAwareBrowser($connection, $this);
149-
150-
// enable target discovery
151-
$connection->sendMessageSync(new Message('Target.setDiscoverTargets', ['discover' => true]));
152149
}
153150

154151
/**

src/BrowserFactory.php

Lines changed: 80 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
use Apix\Log\Logger\Stream as StreamLogger;
99
use HeadlessChromium\Browser\BrowserProcess;
1010
use HeadlessChromium\Browser\ProcessAwareBrowser;
11+
use HeadlessChromium\Communication\Connection;
12+
use HeadlessChromium\Exception\BrowserConnectionFailed;
1113
use Symfony\Component\Process\Process;
14+
use Wrench\Exception\HandshakeException;
1215

1316
class 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
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
/**
3+
* @license see LICENSE
4+
*/
5+
6+
namespace HeadlessChromium\Exception;
7+
8+
class BrowserConnectionFailed extends \Exception
9+
{
10+
11+
}

test/suites/BrowserFactoryTest.php

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,22 @@
66
namespace HeadlessChromium\Test;
77

88
use HeadlessChromium\BrowserFactory;
9+
use HeadlessChromium\Communication\Target;
910

1011
/**
1112
* @covers \HeadlessChromium\BrowserFactory
1213
* @covers \HeadlessChromium\Browser\BrowserProcess
1314
*/
1415
class BrowserFactoryTest extends BaseTestCase
1516
{
17+
public function testBrowserFactory()
18+
{
19+
$factory = new BrowserFactory();
20+
21+
$browser = $factory->createBrowser();
22+
23+
$this->assertRegExp('#^ws://#', $browser->getSocketUri());
24+
}
1625

1726
public function testWindowSizeOption()
1827
{
@@ -44,12 +53,26 @@ public function testUserAgentOption()
4453
$this->assertEquals('foo bar baz', $response);
4554
}
4655

47-
public function testBrowserFactory()
56+
public function testConnectToBrowser()
4857
{
58+
// create a browser
4959
$factory = new BrowserFactory();
50-
5160
$browser = $factory->createBrowser();
5261

53-
$this->assertRegExp('#^ws://#', $browser->getSocketUri());
62+
// TODO test existing pages propagation
63+
64+
// create a new connectionn to the existing browser
65+
$browser2 = BrowserFactory::connectToBrowser($browser->getSocketUri());
66+
67+
// create a page on the first browser after 2d connection
68+
$page2 = $browser->createPage();
69+
$page2TargetId = $page2->getSession()->getTargetId();
70+
71+
// update 2d browser
72+
$browser2->getConnection()->readData();
73+
74+
// make sure 2nd browser received the new page
75+
$target = $browser2->getTarget($page2TargetId);
76+
$this->assertInstanceOf(Target::class, $target);
5477
}
5578
}

0 commit comments

Comments
 (0)