From 3979ec1fdcb1838d06ed601a0a6ffe07ab16966c Mon Sep 17 00:00:00 2001 From: Oleg Andreyev Date: Sat, 28 Dec 2024 18:36:40 +0200 Subject: [PATCH 1/5] added msedgedriver for MacOS --- bdi | 17 +- src/Browser/BrowserName.php | 1 + src/Browser/MsEdge/Command.php | 16 ++ src/Browser/MsEdge/PathResolver.php | 28 +++ src/Browser/MsEdge/VersionResolver.php | 96 +++++++++ src/Driver/DriverFactory.php | 1 + src/Driver/DriverName.php | 1 + src/Driver/MsEdgeDriver/Command.php | 16 ++ .../MsEdgeDriver/DownloadUrlResolver.php | 36 ++++ src/Driver/MsEdgeDriver/Downloader.php | 197 ++++++++++++++++++ src/Driver/MsEdgeDriver/VersionResolver.php | 110 ++++++++++ 11 files changed, 512 insertions(+), 7 deletions(-) create mode 100644 src/Browser/MsEdge/Command.php create mode 100644 src/Browser/MsEdge/PathResolver.php create mode 100644 src/Browser/MsEdge/VersionResolver.php create mode 100644 src/Driver/MsEdgeDriver/Command.php create mode 100644 src/Driver/MsEdgeDriver/DownloadUrlResolver.php create mode 100644 src/Driver/MsEdgeDriver/Downloader.php create mode 100644 src/Driver/MsEdgeDriver/VersionResolver.php diff --git a/bdi b/bdi index d636fab..98b78ff 100755 --- a/bdi +++ b/bdi @@ -10,11 +10,13 @@ use DBrekelmans\BrowserDriverInstaller\Browser; use DBrekelmans\BrowserDriverInstaller\Browser\Chromium; use DBrekelmans\BrowserDriverInstaller\Browser\Firefox; use DBrekelmans\BrowserDriverInstaller\Browser\GoogleChrome; +use DBrekelmans\BrowserDriverInstaller\Browser\MsEdge; use DBrekelmans\BrowserDriverInstaller\Command\DetectCommand; use DBrekelmans\BrowserDriverInstaller\CommandLine\ShellCommandLineEnvironment; use DBrekelmans\BrowserDriverInstaller\Driver; use DBrekelmans\BrowserDriverInstaller\Driver\ChromeDriver; use DBrekelmans\BrowserDriverInstaller\Driver\GeckoDriver; +use DBrekelmans\BrowserDriverInstaller\Driver\MsEdgeDriver; use Symfony\Component\Console\Application; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpClient\NativeHttpClient; @@ -37,23 +39,23 @@ $browserPathResolverFactory = new Browser\PathResolverFactory(); $browserPathResolverFactory->register(new GoogleChrome\PathResolver()); $browserPathResolverFactory->register(new Chromium\PathResolver()); $browserPathResolverFactory->register(new Firefox\PathResolver()); +$browserPathResolverFactory->register(new MsEdge\PathResolver()); $browserVersionResolverFactory = new Browser\VersionResolverFactory(); $browserVersionResolverFactory->register(new GoogleChrome\VersionResolver($shellCommandLineEnv)); $browserVersionResolverFactory->register(new Chromium\VersionResolver($shellCommandLineEnv)); $browserVersionResolverFactory->register(new Firefox\VersionResolver($shellCommandLineEnv)); +$browserVersionResolverFactory->register(new MsEdge\VersionResolver($shellCommandLineEnv)); $driverVersionResolverFactory = new Driver\VersionResolverFactory(); -$chromeDriverVersionResolver = new ChromeDriver\VersionResolver($httpClient); -$geckoDriverVersionResolver = new GeckoDriver\VersionResolver($httpClient); -$driverVersionResolverFactory->register($chromeDriverVersionResolver); -$driverVersionResolverFactory->register($geckoDriverVersionResolver); - -$chromeDriverDownloadUrlResolver = new ChromeDriver\DownloadUrlResolver($httpClient); +$driverVersionResolverFactory->register($chromeDriverVersionResolver = new ChromeDriver\VersionResolver($httpClient)); +$driverVersionResolverFactory->register($geckoDriverVersionResolver = new GeckoDriver\VersionResolver($httpClient)); +$driverVersionResolverFactory->register($msedgeDriverVersionResolver = new MsEdgeDriver\VersionResolver($httpClient)); $driverDownloaderFactory = new Driver\DownloaderFactory(); -$driverDownloaderFactory->register(new ChromeDriver\Downloader($filesystem, $httpClient, $multiExtractor, $chromeDriverDownloadUrlResolver)); +$driverDownloaderFactory->register(new ChromeDriver\Downloader($filesystem, $httpClient, $multiExtractor, $chromeDriverDownloadUrlResolver = new ChromeDriver\DownloadUrlResolver($httpClient))); $driverDownloaderFactory->register(new GeckoDriver\Downloader($filesystem, $httpClient, $multiExtractor)); +$driverDownloaderFactory->register(new MsEdgeDriver\Downloader($filesystem, $httpClient, $multiExtractor, $msedgeDriverDownloadUrlResolver = new MsEdgeDriver\DownloadUrlResolver($httpClient))); $browserFactory = new Browser\BrowserFactory($browserPathResolverFactory, $browserVersionResolverFactory); $driverFactory = new Driver\DriverFactory($driverVersionResolverFactory); @@ -64,6 +66,7 @@ $application->add(new Chromium\Command($filesystem, $browserFactory, $driverFact $application->add(new Firefox\Command($filesystem, $browserFactory, $driverFactory, $driverDownloaderFactory)); $application->add(new ChromeDriver\Command($chromeDriverVersionResolver, $driverDownloaderFactory)); $application->add(new GeckoDriver\Command($geckoDriverVersionResolver, $driverDownloaderFactory)); +$application->add(new MsEdge\Command($filesystem, $browserFactory, $driverFactory, $driverDownloaderFactory)); $application->setDefaultCommand(DetectCommand::NAME); diff --git a/src/Browser/BrowserName.php b/src/Browser/BrowserName.php index ab7d55d..f9af067 100644 --- a/src/Browser/BrowserName.php +++ b/src/Browser/BrowserName.php @@ -9,4 +9,5 @@ enum BrowserName: string case GOOGLE_CHROME = 'google-chrome'; case CHROMIUM = 'chromium'; case FIREFOX = 'firefox'; + case MSEDGE = 'msedge'; } diff --git a/src/Browser/MsEdge/Command.php b/src/Browser/MsEdge/Command.php new file mode 100644 index 0000000..b54f4c0 --- /dev/null +++ b/src/Browser/MsEdge/Command.php @@ -0,0 +1,16 @@ + 'chromium', + OperatingSystem::MACOS => '/Applications/Microsoft\ Edge.app', + // TODO +// OperatingSystem::WINDOWS => 'C:\\Program Files (x86)\\Chromium\\Application\\chrome.exe', + }; + } + + public function supports(BrowserName $browserName): bool + { + return $browserName === BrowserName::MSEDGE; + } +} diff --git a/src/Browser/MsEdge/VersionResolver.php b/src/Browser/MsEdge/VersionResolver.php new file mode 100644 index 0000000..c35b464 --- /dev/null +++ b/src/Browser/MsEdge/VersionResolver.php @@ -0,0 +1,96 @@ + NUL'; + private const VERSION_REG_QUERY_CURRENT_USER = 'reg query HKCU\Software\Google\Update\Clients\{%s} /v pv /reg:32 2> NUL'; + + public function __construct(private readonly CommandLineEnvironment $commandLineEnvironment) + { + } + + public function from(OperatingSystem $operatingSystem, string $path): Version + { + return match ($operatingSystem) { + // TODO +// OperatingSystem::LINUX => $this->getVersionFromCommandLine(sprintf('%s --version', $path)), + OperatingSystem::MACOS => $this->getVersionFromCommandLine(sprintf('%s/Contents/MacOS/Microsoft\ Edge --version', $path)), + // TODO +// OperatingSystem::WINDOWS => $this->getVersionFromWindows(), + }; + } + + public function supports(BrowserName $browserName): bool + { + return $browserName === BrowserName::MSEDGE; + } + + private function getVersionFromWindows(): Version + { + foreach (self::getWindowsCommandsForVersion() as $possibleCommand) { + try { + return $this->getVersionFromCommandLine($possibleCommand); + } catch (InvalidArgumentException) { + // @ignoreException + } + } + + throw new InvalidArgumentException('Version could not be determined.'); + } + + private function getVersionFromCommandLine(string $command): Version + { + try { + $commandOutput = $this->commandLineEnvironment->getCommandLineSuccessfulOutput($command); + + return Version::fromString($commandOutput); + } catch (RuntimeException $exception) { + throw new RuntimeException( + 'Version could not be determined.', + 0, + $exception, + ); + } + } + + /** + * Provide potential commands to determine Chromium Version on Windows + * + * @see https://bugs.chromium.org/p/chromium/issues/attachmentText?aid=387709 + * @see https://bugs.chromium.org/p/chromium/issues/detail?id=158372 + * + * @return string[] + */ + private static function getWindowsCommandsForVersion(): array + { + $commands = []; + foreach ([self::REG_KEY_STABLE, self::REG_KEY_BETA, self::REG_KEY_DEV] as $regKey) { + $commands[] = sprintf(self::VERSION_REG_QUERY_LOCAL_MACHINE, $regKey); + } + + foreach ([self::REG_KEY_STABLE, self::REG_KEY_BETA, self::REG_KEY_DEV, self::REG_KEY_CANARY] as $regKey) { + $commands[] = sprintf(self::VERSION_REG_QUERY_CURRENT_USER, $regKey); + } + + return $commands; + } +} diff --git a/src/Driver/DriverFactory.php b/src/Driver/DriverFactory.php index d676c83..55d2872 100644 --- a/src/Driver/DriverFactory.php +++ b/src/Driver/DriverFactory.php @@ -28,6 +28,7 @@ private function getDriverNameForBrowser(Browser $browser): DriverName return match ($browser->name) { BrowserName::GOOGLE_CHROME, BrowserName::CHROMIUM => DriverName::CHROME, BrowserName::FIREFOX => DriverName::GECKO, + BrowserName::MSEDGE => DriverName::MSEDGE, }; } } diff --git a/src/Driver/DriverName.php b/src/Driver/DriverName.php index 8184fdd..3c3e115 100644 --- a/src/Driver/DriverName.php +++ b/src/Driver/DriverName.php @@ -8,4 +8,5 @@ enum DriverName: string { case CHROME = 'chromedriver'; case GECKO = 'geckodriver'; + case MSEDGE = 'msedgedriver'; } diff --git a/src/Driver/MsEdgeDriver/Command.php b/src/Driver/MsEdgeDriver/Command.php new file mode 100644 index 0000000..f424936 --- /dev/null +++ b/src/Driver/MsEdgeDriver/Command.php @@ -0,0 +1,16 @@ +version->toBuildString(), + $this->getBinaryName($driver), + ); + } + + private function getBinaryName(Driver $driver): string + { + // https://msedgewebdriverstorage.z22.web.core.windows.net/?prefix=131.0.2903.112/ + return match ($driver->operatingSystem) { + OperatingSystem::LINUX => 'edgedriver_linux64', + OperatingSystem::MACOS => 'edgedriver_mac64', + OperatingSystem::WINDOWS => 'edgedriver_win32', + }; + } +} diff --git a/src/Driver/MsEdgeDriver/Downloader.php b/src/Driver/MsEdgeDriver/Downloader.php new file mode 100644 index 0000000..06245b8 --- /dev/null +++ b/src/Driver/MsEdgeDriver/Downloader.php @@ -0,0 +1,197 @@ +tempDir = sys_get_temp_dir(); + } + + public function supports(Driver $driver): bool + { + return $driver->name === DriverName::MSEDGE; + } + + /** @throws RuntimeException */ + public function download(Driver $driver, string $location): string + { + try { + $archive = $this->downloadArchive($driver); + } catch (NotImplemented | FilesystemException | IOException | TransportExceptionInterface $exception) { + throw new RuntimeException('Something went wrong downloading the msedgedriver archive.', 0, $exception); + } + + try { + $binary = $this->extractArchive($archive, $driver); + } catch (IOException | RuntimeException $exception) { + throw new RuntimeException('Something went wrong extracting the msedgedriver archive.', 0, $exception); + } + + $filePath = $this->getFilePath($location, $driver->operatingSystem); + + if (! $this->filesystem->exists($location)) { + $this->filesystem->mkdir($location); + } + + try { + $this->filesystem->rename($binary, $filePath, true); + } catch (IOException $exception) { + throw new RuntimeException( + sprintf('Something went wrong moving the msedgedriver to %s.', $location), + 0, + $exception, + ); + } + + $mode = 0755; + try { + $this->filesystem->chmod($filePath, $mode); + } catch (IOException $exception) { + throw new RuntimeException( + sprintf('Something went wrong setting the permissions of the msedgedriver to %d.', $mode), + 0, + $exception, + ); + } + + return $filePath; + } + + /** + * @throws NotImplemented + * @throws TransportExceptionInterface + * @throws FilesystemException + * @throws IOException + */ + private function downloadArchive(Driver $driver): string + { + $temporaryFile = $this->filesystem->tempnam($this->tempDir, 'msedgedriver', '.zip'); + + $response = $this->httpClient->request( + 'GET', + $this->downloadUrlResolver->byDriver($driver), + ); + + $fileHandler = fopen($temporaryFile, 'wb'); + + try { + foreach ($this->httpClient->stream($response) as $chunk) { + fwrite($fileHandler, $chunk->getContent()); + } + } catch (TransportExceptionInterface $exception) { + throw $exception; + } finally { + fclose($fileHandler); + } + + return $temporaryFile; + } + + /** + * @throws RuntimeException + * @throws IOException + */ + private function extractArchive(string $archive, Driver $driver): string + { + $unzipLocation = $this->tempDir . DIRECTORY_SEPARATOR . 'msedgedriver'; + $extractedFiles = $this->archiveExtractor->extract($archive, $unzipLocation); + $filePath = $this->getFilePath($unzipLocation, $driver->operatingSystem); + + if ( + ! in_array( + $filePath, + $extractedFiles, + true, + ) + ) { + throw new UnexpectedValueException(sprintf('Could not find "%s" in the extracted files.', $filePath)); + } + + $file = $this->filesystem->readlink($filePath, true); + if ($file === null) { + throw new RuntimeException(sprintf('Could not read link %s', $filePath)); + } + + $this->filesystem->remove($archive); + + return $file; + } + + private function getFilePath(string $location, OperatingSystem $operatingSystem): string + { + return $location . DIRECTORY_SEPARATOR . $this->getFileName($operatingSystem); + } + + private function getFileName(OperatingSystem $operatingSystem): string + { + $fileName = 'msedgedriver'; + + if ($operatingSystem === OperatingSystem::WINDOWS) { + $fileName .= '.exe'; + } + + return $fileName; + } + + /** + * @param string[] $extractedFiles + * + * @return string[] + */ + public function cleanArchiveStructure(Driver $driver, string $unzipLocation, array $extractedFiles): array + { + $archiveDirectory = $this->getArchiveDirectory($driver->operatingSystem); + $filename = $this->getFileName($driver->operatingSystem); + $this->filesystem->rename( + $unzipLocation . DIRECTORY_SEPARATOR . $archiveDirectory . $filename, + $unzipLocation . DIRECTORY_SEPARATOR . $filename, + true, + ); + + return str_replace($archiveDirectory, '', $extractedFiles); + } + + private function getArchiveDirectory(OperatingSystem $operatingSystem): string + { + return match ($operatingSystem) { + OperatingSystem::LINUX => 'msedgedriver-linux64/', + OperatingSystem::WINDOWS => 'msedgedriver-win32/', // This weirdly contains a forward slash on windows + OperatingSystem::MACOS => 'msedgedriver-mac-x64/', + }; + } +} diff --git a/src/Driver/MsEdgeDriver/VersionResolver.php b/src/Driver/MsEdgeDriver/VersionResolver.php new file mode 100644 index 0000000..e2341de --- /dev/null +++ b/src/Driver/MsEdgeDriver/VersionResolver.php @@ -0,0 +1,110 @@ +supports($browser)) { + throw new Unsupported(sprintf('%s is not supported.', $browser->name->value)); + } + + try { + $versionString = $this->getVersionString($browser); + } catch ( + ClientExceptionInterface + | RedirectionExceptionInterface + | ServerExceptionInterface + | TransportExceptionInterface + $exception + ) { + throw new UnexpectedValueException( + 'Something went wrong getting the driver version from the chromedriver API.', + 0, + $exception, + ); + } + + try { + return Version::fromString($versionString); + } catch (InvalidArgumentException $exception) { + throw new UnexpectedValueException( + 'Content received from chromedriver API could not be parsed into a version.', + 0, + $exception, + ); + } + } + + public function latest(): Version + { + $response = $this->httpClient->request('GET', self::LATEST_STABLE_VERSION_ENDPOINT); + $version = $response->getContent(); + $version = str_replace(chr(0), '', substr($version, 2)); + + return Version::fromString((string) $version); + } + + public function supports(Browser $browser): bool + { + return $browser->name === BrowserName::MSEDGE; + } + + private function latestBetaVersion(): Version + { + $response = $this->httpClient->request('GET', self::LATEST_BETA_VERSION_ENDPOINT); + $version = $response->getContent(); + $version = str_replace(chr(0), '', substr($version, 2)); + + return Version::fromString((string) $version); + } + + /** + * @throws RedirectionExceptionInterface + * @throws ClientExceptionInterface + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + * @throws DecodingExceptionInterface + */ + private function getVersionString(Browser $browser): string + { + $latestBeta = $this->latestBetaVersion(); + + $version = $browser->version; + if ((int) $version->major() > (int) $latestBeta->major()) { + // In this case we're dealing with a Dev or Canary version, so we will take the last Beta version. + $version = $latestBeta; + } + + return $version->toBuildString(); + } +} From 986fc9ab6fb150cba307aaf0ff8f051fe8a25a38 Mon Sep 17 00:00:00 2001 From: Oleg Andreyev Date: Sat, 28 Dec 2024 18:41:06 +0200 Subject: [PATCH 2/5] phpstan * phpcbf --- bdi | 2 +- src/Browser/MsEdge/PathResolver.php | 7 ++- src/Browser/MsEdge/VersionResolver.php | 50 +-------------------- src/Driver/MsEdgeDriver/Downloader.php | 2 +- src/Driver/MsEdgeDriver/VersionResolver.php | 4 +- 5 files changed, 9 insertions(+), 56 deletions(-) diff --git a/bdi b/bdi index 98b78ff..4cd468f 100755 --- a/bdi +++ b/bdi @@ -55,7 +55,7 @@ $driverVersionResolverFactory->register($msedgeDriverVersionResolver = new MsEdg $driverDownloaderFactory = new Driver\DownloaderFactory(); $driverDownloaderFactory->register(new ChromeDriver\Downloader($filesystem, $httpClient, $multiExtractor, $chromeDriverDownloadUrlResolver = new ChromeDriver\DownloadUrlResolver($httpClient))); $driverDownloaderFactory->register(new GeckoDriver\Downloader($filesystem, $httpClient, $multiExtractor)); -$driverDownloaderFactory->register(new MsEdgeDriver\Downloader($filesystem, $httpClient, $multiExtractor, $msedgeDriverDownloadUrlResolver = new MsEdgeDriver\DownloadUrlResolver($httpClient))); +$driverDownloaderFactory->register(new MsEdgeDriver\Downloader($filesystem, $httpClient, $multiExtractor, $msedgeDriverDownloadUrlResolver = new MsEdgeDriver\DownloadUrlResolver())); $browserFactory = new Browser\BrowserFactory($browserPathResolverFactory, $browserVersionResolverFactory); $driverFactory = new Driver\DriverFactory($driverVersionResolverFactory); diff --git a/src/Browser/MsEdge/PathResolver.php b/src/Browser/MsEdge/PathResolver.php index 0849bd7..77f05fe 100644 --- a/src/Browser/MsEdge/PathResolver.php +++ b/src/Browser/MsEdge/PathResolver.php @@ -7,17 +7,16 @@ use DBrekelmans\BrowserDriverInstaller\Browser\BrowserName; use DBrekelmans\BrowserDriverInstaller\Browser\PathResolver as PathResolverInterface; use DBrekelmans\BrowserDriverInstaller\OperatingSystem\OperatingSystem; +use RuntimeException; class PathResolver implements PathResolverInterface { public function from(OperatingSystem $operatingSystem): string { return match ($operatingSystem) { - // TODO -// OperatingSystem::LINUX => 'chromium', + OperatingSystem::LINUX => throw new RuntimeException('Not implemented yet.'), OperatingSystem::MACOS => '/Applications/Microsoft\ Edge.app', - // TODO -// OperatingSystem::WINDOWS => 'C:\\Program Files (x86)\\Chromium\\Application\\chrome.exe', + OperatingSystem::WINDOWS => throw new RuntimeException('Not implemented yet.'), }; } diff --git a/src/Browser/MsEdge/VersionResolver.php b/src/Browser/MsEdge/VersionResolver.php index c35b464..c15cab2 100644 --- a/src/Browser/MsEdge/VersionResolver.php +++ b/src/Browser/MsEdge/VersionResolver.php @@ -9,21 +9,12 @@ use DBrekelmans\BrowserDriverInstaller\CommandLine\CommandLineEnvironment; use DBrekelmans\BrowserDriverInstaller\OperatingSystem\OperatingSystem; use DBrekelmans\BrowserDriverInstaller\Version; -use InvalidArgumentException; use RuntimeException; use function sprintf; final class VersionResolver implements VersionResolverInterface { - // TODO - private const REG_KEY_STABLE = '8A69D345-D564-463c-AFF1-A69D9E530F96'; - private const REG_KEY_BETA = '8237E44A-0054-442C-B6B6-EA0509993955'; - private const REG_KEY_DEV = '401C381F-E0DE-4B85-8BD8-3F3F14FBDA57'; - private const REG_KEY_CANARY = '4ea16ac7-fd5a-47c3-875b-dbf4a2008c20'; - private const VERSION_REG_QUERY_LOCAL_MACHINE = 'reg query HKLM\Software\Google\Update\Clients\{%s} /v pv /reg:32 2> NUL'; - private const VERSION_REG_QUERY_CURRENT_USER = 'reg query HKCU\Software\Google\Update\Clients\{%s} /v pv /reg:32 2> NUL'; - public function __construct(private readonly CommandLineEnvironment $commandLineEnvironment) { } @@ -31,11 +22,9 @@ public function __construct(private readonly CommandLineEnvironment $commandLine public function from(OperatingSystem $operatingSystem, string $path): Version { return match ($operatingSystem) { - // TODO -// OperatingSystem::LINUX => $this->getVersionFromCommandLine(sprintf('%s --version', $path)), + OperatingSystem::LINUX => throw new RuntimeException('Not implemented yet.'), OperatingSystem::MACOS => $this->getVersionFromCommandLine(sprintf('%s/Contents/MacOS/Microsoft\ Edge --version', $path)), - // TODO -// OperatingSystem::WINDOWS => $this->getVersionFromWindows(), + OperatingSystem::WINDOWS => throw new RuntimeException('Not implemented yet.'), }; } @@ -44,19 +33,6 @@ public function supports(BrowserName $browserName): bool return $browserName === BrowserName::MSEDGE; } - private function getVersionFromWindows(): Version - { - foreach (self::getWindowsCommandsForVersion() as $possibleCommand) { - try { - return $this->getVersionFromCommandLine($possibleCommand); - } catch (InvalidArgumentException) { - // @ignoreException - } - } - - throw new InvalidArgumentException('Version could not be determined.'); - } - private function getVersionFromCommandLine(string $command): Version { try { @@ -71,26 +47,4 @@ private function getVersionFromCommandLine(string $command): Version ); } } - - /** - * Provide potential commands to determine Chromium Version on Windows - * - * @see https://bugs.chromium.org/p/chromium/issues/attachmentText?aid=387709 - * @see https://bugs.chromium.org/p/chromium/issues/detail?id=158372 - * - * @return string[] - */ - private static function getWindowsCommandsForVersion(): array - { - $commands = []; - foreach ([self::REG_KEY_STABLE, self::REG_KEY_BETA, self::REG_KEY_DEV] as $regKey) { - $commands[] = sprintf(self::VERSION_REG_QUERY_LOCAL_MACHINE, $regKey); - } - - foreach ([self::REG_KEY_STABLE, self::REG_KEY_BETA, self::REG_KEY_DEV, self::REG_KEY_CANARY] as $regKey) { - $commands[] = sprintf(self::VERSION_REG_QUERY_CURRENT_USER, $regKey); - } - - return $commands; - } } diff --git a/src/Driver/MsEdgeDriver/Downloader.php b/src/Driver/MsEdgeDriver/Downloader.php index 06245b8..f60f2db 100644 --- a/src/Driver/MsEdgeDriver/Downloader.php +++ b/src/Driver/MsEdgeDriver/Downloader.php @@ -130,7 +130,7 @@ private function extractArchive(string $archive, Driver $driver): string { $unzipLocation = $this->tempDir . DIRECTORY_SEPARATOR . 'msedgedriver'; $extractedFiles = $this->archiveExtractor->extract($archive, $unzipLocation); - $filePath = $this->getFilePath($unzipLocation, $driver->operatingSystem); + $filePath = $this->getFilePath($unzipLocation, $driver->operatingSystem); if ( ! in_array( diff --git a/src/Driver/MsEdgeDriver/VersionResolver.php b/src/Driver/MsEdgeDriver/VersionResolver.php index e2341de..05ae76c 100644 --- a/src/Driver/MsEdgeDriver/VersionResolver.php +++ b/src/Driver/MsEdgeDriver/VersionResolver.php @@ -71,7 +71,7 @@ public function latest(): Version $version = $response->getContent(); $version = str_replace(chr(0), '', substr($version, 2)); - return Version::fromString((string) $version); + return Version::fromString($version); } public function supports(Browser $browser): bool @@ -85,7 +85,7 @@ private function latestBetaVersion(): Version $version = $response->getContent(); $version = str_replace(chr(0), '', substr($version, 2)); - return Version::fromString((string) $version); + return Version::fromString($version); } /** From a00011a6bcc90b6a27b0cc263c5776b14e1ffc24 Mon Sep 17 00:00:00 2001 From: Oleg Andreyev Date: Sat, 28 Dec 2024 18:44:57 +0200 Subject: [PATCH 3/5] fix: minor message correction --- src/Driver/MsEdgeDriver/VersionResolver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Driver/MsEdgeDriver/VersionResolver.php b/src/Driver/MsEdgeDriver/VersionResolver.php index 05ae76c..af927c5 100644 --- a/src/Driver/MsEdgeDriver/VersionResolver.php +++ b/src/Driver/MsEdgeDriver/VersionResolver.php @@ -48,7 +48,7 @@ public function fromBrowser(Browser $browser): Version $exception ) { throw new UnexpectedValueException( - 'Something went wrong getting the driver version from the chromedriver API.', + 'Something went wrong getting the driver version from the msedgedriver API.', 0, $exception, ); @@ -58,7 +58,7 @@ public function fromBrowser(Browser $browser): Version return Version::fromString($versionString); } catch (InvalidArgumentException $exception) { throw new UnexpectedValueException( - 'Content received from chromedriver API could not be parsed into a version.', + 'Content received from msedgedriver API could not be parsed into a version.', 0, $exception, ); From 43fe8088d9771f75d7e532b9d21098e9b2b70bb6 Mon Sep 17 00:00:00 2001 From: Oleg Andreyev Date: Sun, 29 Dec 2024 00:16:51 +0200 Subject: [PATCH 4/5] added logic for Windows --- src/Browser/MsEdge/PathResolver.php | 2 +- src/Browser/MsEdge/VersionResolver.php | 30 ++++++++++++++++++- .../MsEdgeDriver/DownloadUrlResolver.php | 2 +- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/Browser/MsEdge/PathResolver.php b/src/Browser/MsEdge/PathResolver.php index 77f05fe..c31d80a 100644 --- a/src/Browser/MsEdge/PathResolver.php +++ b/src/Browser/MsEdge/PathResolver.php @@ -16,7 +16,7 @@ public function from(OperatingSystem $operatingSystem): string return match ($operatingSystem) { OperatingSystem::LINUX => throw new RuntimeException('Not implemented yet.'), OperatingSystem::MACOS => '/Applications/Microsoft\ Edge.app', - OperatingSystem::WINDOWS => throw new RuntimeException('Not implemented yet.'), + OperatingSystem::WINDOWS => 'C:\Program Files (x86)\Microsoft\Edge\Application', }; } diff --git a/src/Browser/MsEdge/VersionResolver.php b/src/Browser/MsEdge/VersionResolver.php index c15cab2..c2743d8 100644 --- a/src/Browser/MsEdge/VersionResolver.php +++ b/src/Browser/MsEdge/VersionResolver.php @@ -9,6 +9,7 @@ use DBrekelmans\BrowserDriverInstaller\CommandLine\CommandLineEnvironment; use DBrekelmans\BrowserDriverInstaller\OperatingSystem\OperatingSystem; use DBrekelmans\BrowserDriverInstaller\Version; +use InvalidArgumentException; use RuntimeException; use function sprintf; @@ -24,7 +25,7 @@ public function from(OperatingSystem $operatingSystem, string $path): Version return match ($operatingSystem) { OperatingSystem::LINUX => throw new RuntimeException('Not implemented yet.'), OperatingSystem::MACOS => $this->getVersionFromCommandLine(sprintf('%s/Contents/MacOS/Microsoft\ Edge --version', $path)), - OperatingSystem::WINDOWS => throw new RuntimeException('Not implemented yet.'), + OperatingSystem::WINDOWS => $this->getVersionFromWindows(), }; } @@ -33,6 +34,33 @@ public function supports(BrowserName $browserName): bool return $browserName === BrowserName::MSEDGE; } + private function getVersionFromWindows(): Version + { + $previousException = null; + foreach (self::getWindowsCommandsForVersion() as $possibleCommand) { + try { + return $this->getVersionFromCommandLine($possibleCommand); + } catch (InvalidArgumentException $exception) { + $previousException = $exception; + } + } + + throw new InvalidArgumentException('Version could not be determined.', 0, $previousException); + } + + /** + * Provide potential commands to determine Edge Version on Windows + * + * @return string[] + */ + private static function getWindowsCommandsForVersion(): array + { + return [ + "powershell \"(Get-Item 'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe').VersionInfo.ProductVersion\"", + 'reg query HKCU\Software\Microsoft\Edge\BLBeacon /v version', + ]; + } + private function getVersionFromCommandLine(string $command): Version { try { diff --git a/src/Driver/MsEdgeDriver/DownloadUrlResolver.php b/src/Driver/MsEdgeDriver/DownloadUrlResolver.php index 9bee727..aa26f0b 100644 --- a/src/Driver/MsEdgeDriver/DownloadUrlResolver.php +++ b/src/Driver/MsEdgeDriver/DownloadUrlResolver.php @@ -30,7 +30,7 @@ private function getBinaryName(Driver $driver): string return match ($driver->operatingSystem) { OperatingSystem::LINUX => 'edgedriver_linux64', OperatingSystem::MACOS => 'edgedriver_mac64', - OperatingSystem::WINDOWS => 'edgedriver_win32', + OperatingSystem::WINDOWS => 'edgedriver_win64', // TODO: 32bit? }; } } From 080d9a81c361f9a65dbee217d85645238d264e05 Mon Sep 17 00:00:00 2001 From: Oleg Andreyev Date: Sun, 29 Dec 2024 00:51:38 +0200 Subject: [PATCH 5/5] detect more versions --- src/Browser/MsEdge/VersionResolver.php | 15 ++++- src/Driver/MsEdgeDriver/VersionResolver.php | 66 ++++++++++++++------- 2 files changed, 57 insertions(+), 24 deletions(-) diff --git a/src/Browser/MsEdge/VersionResolver.php b/src/Browser/MsEdge/VersionResolver.php index c2743d8..61f90fb 100644 --- a/src/Browser/MsEdge/VersionResolver.php +++ b/src/Browser/MsEdge/VersionResolver.php @@ -55,10 +55,19 @@ private function getVersionFromWindows(): Version */ private static function getWindowsCommandsForVersion(): array { - return [ - "powershell \"(Get-Item 'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe').VersionInfo.ProductVersion\"", - 'reg query HKCU\Software\Microsoft\Edge\BLBeacon /v version', + $versions = [ + 'Edge', + 'Edge Beta', + 'Edge Dev', + 'Edge SxS', ]; + + $commands = []; + foreach ($versions as $version) { + $commands[] = sprintf('reg query HKCU\Software\Microsoft\%s\BLBeacon /v version', $version); + } + + return $commands; } private function getVersionFromCommandLine(string $command): Version diff --git a/src/Driver/MsEdgeDriver/VersionResolver.php b/src/Driver/MsEdgeDriver/VersionResolver.php index af927c5..628f924 100644 --- a/src/Driver/MsEdgeDriver/VersionResolver.php +++ b/src/Driver/MsEdgeDriver/VersionResolver.php @@ -27,6 +27,8 @@ final class VersionResolver implements VersionResolverInterface { private const LATEST_STABLE_VERSION_ENDPOINT = 'https://msedgedriver.azureedge.net/LATEST_STABLE'; private const LATEST_BETA_VERSION_ENDPOINT = 'https://msedgedriver.azureedge.net/LATEST_BETA'; + private const LATEST_DEV_VERSION_ENDPOINT = 'https://msedgedriver.azureedge.net/LATEST_DEV'; + private const LATEST_CANARY_VERSION_ENDPOINT = 'https://msedgedriver.azureedge.net/LATEST_CANARY'; public function __construct(private readonly HttpClientInterface $httpClient) { @@ -65,29 +67,11 @@ public function fromBrowser(Browser $browser): Version } } - public function latest(): Version - { - $response = $this->httpClient->request('GET', self::LATEST_STABLE_VERSION_ENDPOINT); - $version = $response->getContent(); - $version = str_replace(chr(0), '', substr($version, 2)); - - return Version::fromString($version); - } - public function supports(Browser $browser): bool { return $browser->name === BrowserName::MSEDGE; } - private function latestBetaVersion(): Version - { - $response = $this->httpClient->request('GET', self::LATEST_BETA_VERSION_ENDPOINT); - $version = $response->getContent(); - $version = str_replace(chr(0), '', substr($version, 2)); - - return Version::fromString($version); - } - /** * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface @@ -97,14 +81,54 @@ private function latestBetaVersion(): Version */ private function getVersionString(Browser $browser): string { + $latestStable = $this->latestStableVersion(); $latestBeta = $this->latestBetaVersion(); + $latestDev = $this->latestDevVersion(); + $latestCanary = $this->latestCanaryVersion(); $version = $browser->version; - if ((int) $version->major() > (int) $latestBeta->major()) { - // In this case we're dealing with a Dev or Canary version, so we will take the last Beta version. - $version = $latestBeta; + // In this case we're dealing with a Dev or Canary version, so we will take the last Beta version. + $versions = [$latestStable, $latestBeta, $latestDev, $latestCanary]; + foreach ($versions as $ver) { + if (version_compare($version->toString(), $ver->toString(), '>=')) { + $version = $ver; + } } return $version->toBuildString(); } + + public function latestStableVersion(): Version + { + return $this->request(self::LATEST_STABLE_VERSION_ENDPOINT); + } + + private function latestBetaVersion(): Version + { + return $this->request(self::LATEST_BETA_VERSION_ENDPOINT); + } + + private function latestDevVersion(): Version + { + return $this->request(self::LATEST_DEV_VERSION_ENDPOINT); + } + + private function latestCanaryVersion(): Version + { + return $this->request(self::LATEST_CANARY_VERSION_ENDPOINT); + } + + public function request(string $url): Version + { + $response = $this->httpClient->request('GET', $url); + $version = $response->getContent(); + $version = str_replace(chr(0), '', substr($version, 2)); + + return Version::fromString($version); + } + + public function latest(): Version + { + return $this->latestStableVersion(); + } }