|  | // Copyright 2014 The Flutter Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | import 'dart:async'; | 
|  |  | 
|  | import 'package:file/memory.dart'; | 
|  | import 'package:flutter_tools/src/base/common.dart'; | 
|  | import 'package:flutter_tools/src/base/file_system.dart'; | 
|  | import 'package:flutter_tools/src/base/logger.dart'; | 
|  | import 'package:flutter_tools/src/base/os.dart'; | 
|  | import 'package:flutter_tools/src/web/chrome.dart'; | 
|  | import 'package:mockito/mockito.dart'; | 
|  | import 'package:platform/platform.dart'; | 
|  |  | 
|  | import '../../src/common.dart'; | 
|  | import '../../src/context.dart'; | 
|  |  | 
|  | const List<String> _kChromeArgs = <String>[ | 
|  | '--disable-background-timer-throttling', | 
|  | '--disable-extensions', | 
|  | '--disable-popup-blocking', | 
|  | '--bwsi', | 
|  | '--no-first-run', | 
|  | '--no-default-browser-check', | 
|  | '--disable-default-apps', | 
|  | '--disable-translate', | 
|  | ]; | 
|  |  | 
|  | const String kDevtoolsStderr = '\n\nDevTools listening\n\n'; | 
|  |  | 
|  | void main() { | 
|  | ChromeLauncher chromeLauncher; | 
|  | FileSystem fileSystem; | 
|  | Platform platform; | 
|  | FakeProcessManager processManager; | 
|  | OperatingSystemUtils operatingSystemUtils; | 
|  | Logger logger; | 
|  |  | 
|  | setUp(() { | 
|  | logger = BufferLogger.test(); | 
|  | operatingSystemUtils = MockOperatingSystemUtils(); | 
|  | when(operatingSystemUtils.findFreePort()) | 
|  | .thenAnswer((Invocation invocation) async { | 
|  | return 1234; | 
|  | }); | 
|  | platform = FakePlatform(operatingSystem: 'macos', environment: <String, String>{ | 
|  | kChromeEnvironment: 'example_chrome', | 
|  | }); | 
|  | fileSystem = MemoryFileSystem.test(); | 
|  | processManager = FakeProcessManager.list(<FakeCommand>[]); | 
|  | chromeLauncher = ChromeLauncher( | 
|  | fileSystem: fileSystem, | 
|  | platform: platform, | 
|  | processManager: processManager, | 
|  | operatingSystemUtils: operatingSystemUtils, | 
|  | logger: logger, | 
|  | ); | 
|  | }); | 
|  |  | 
|  | tearDown(() { | 
|  | resetChromeForTesting(); | 
|  | }); | 
|  |  | 
|  | test('can launch chrome and connect to the devtools', () async { | 
|  | await testLaunchChrome('/.tmp_rand0/flutter_tools_chrome_device.rand0', processManager, chromeLauncher); | 
|  | }); | 
|  |  | 
|  | test('cannot have two concurrent instances of chrome', () async { | 
|  | await testLaunchChrome('/.tmp_rand0/flutter_tools_chrome_device.rand0', processManager, chromeLauncher); | 
|  | bool pass = false; | 
|  | try { | 
|  | await testLaunchChrome('/.tmp_rand0/flutter_tools_chrome_device.rand1', processManager, chromeLauncher); | 
|  | } on ToolExit catch (_) { | 
|  | pass = true; | 
|  | } | 
|  | expect(pass, isTrue); | 
|  | }); | 
|  |  | 
|  | test('can launch new chrome after stopping a previous chrome', () async { | 
|  | final Chrome  chrome = await testLaunchChrome('/.tmp_rand0/flutter_tools_chrome_device.rand0', processManager, chromeLauncher); | 
|  | await chrome.close(); | 
|  | await testLaunchChrome('/.tmp_rand0/flutter_tools_chrome_device.rand1', processManager, chromeLauncher); | 
|  | }); | 
|  |  | 
|  | test('can launch chrome with a custom debug port', () async { | 
|  | processManager.addCommand(const FakeCommand( | 
|  | command: <String>[ | 
|  | 'example_chrome', | 
|  | '--user-data-dir=/.tmp_rand1/flutter_tools_chrome_device.rand1', | 
|  | '--remote-debugging-port=10000', | 
|  | ..._kChromeArgs, | 
|  | 'example_url', | 
|  | ], | 
|  | stderr: kDevtoolsStderr, | 
|  | )); | 
|  |  | 
|  | await chromeLauncher.launch( | 
|  | 'example_url', | 
|  | skipCheck: true, | 
|  | debugPort: 10000, | 
|  | ); | 
|  | }); | 
|  |  | 
|  | test('can launch chrome headless', () async { | 
|  | processManager.addCommand(const FakeCommand( | 
|  | command: <String>[ | 
|  | 'example_chrome', | 
|  | '--user-data-dir=/.tmp_rand1/flutter_tools_chrome_device.rand1', | 
|  | '--remote-debugging-port=1234', | 
|  | ..._kChromeArgs, | 
|  | '--headless', | 
|  | '--disable-gpu', | 
|  | '--no-sandbox', | 
|  | '--window-size=2400,1800', | 
|  | 'example_url', | 
|  | ], | 
|  | stderr: kDevtoolsStderr, | 
|  | )); | 
|  |  | 
|  | await chromeLauncher.launch( | 
|  | 'example_url', | 
|  | skipCheck: true, | 
|  | headless: true, | 
|  | ); | 
|  | }); | 
|  |  | 
|  | test('can seed chrome temp directory with existing session data', () async { | 
|  | final Completer<void> exitCompleter = Completer<void>.sync(); | 
|  | final Directory dataDir = fileSystem.directory('chrome-stuff'); | 
|  |  | 
|  | final File preferencesFile = dataDir | 
|  | .childDirectory('Default') | 
|  | .childFile('preferences'); | 
|  | preferencesFile | 
|  | ..createSync(recursive: true) | 
|  | ..writeAsStringSync('example'); | 
|  |  | 
|  | final Directory localStorageContentsDirectory = dataDir | 
|  | .childDirectory('Default') | 
|  | .childDirectory('Local Storage') | 
|  | .childDirectory('leveldb'); | 
|  | localStorageContentsDirectory.createSync(recursive: true); | 
|  | localStorageContentsDirectory.childFile('LOCK').writeAsBytesSync(<int>[]); | 
|  | localStorageContentsDirectory.childFile('LOG').writeAsStringSync('contents'); | 
|  |  | 
|  | processManager.addCommand(FakeCommand(command: const <String>[ | 
|  | 'example_chrome', | 
|  | '--user-data-dir=/.tmp_rand1/flutter_tools_chrome_device.rand1', | 
|  | '--remote-debugging-port=1234', | 
|  | ..._kChromeArgs, | 
|  | 'example_url', | 
|  | ], completer: exitCompleter)); | 
|  |  | 
|  | await chromeLauncher.launch( | 
|  | 'example_url', | 
|  | skipCheck: true, | 
|  | cacheDir: dataDir, | 
|  | ); | 
|  |  | 
|  | // validate preferences | 
|  | final File tempFile = fileSystem | 
|  | .directory('.tmp_rand1/flutter_tools_chrome_device.rand1') | 
|  | .childDirectory('Default') | 
|  | .childFile('preferences'); | 
|  |  | 
|  | expect(tempFile.existsSync(), true); | 
|  | expect(tempFile.readAsStringSync(), 'example'); | 
|  |  | 
|  | // write crash to file: | 
|  | tempFile.writeAsStringSync('"exit_type":"Crashed"'); | 
|  | exitCompleter.complete(); | 
|  |  | 
|  | // writes non-crash back to dart_tool | 
|  | expect(preferencesFile.readAsStringSync(), '"exit_type":"Normal"'); | 
|  |  | 
|  | // validate local storage | 
|  | final Directory storageDir = fileSystem | 
|  | .directory('.tmp_rand1/flutter_tools_chrome_device.rand1') | 
|  | .childDirectory('Default') | 
|  | .childDirectory('Local Storage') | 
|  | .childDirectory('leveldb'); | 
|  |  | 
|  | expect(storageDir.existsSync(), true); | 
|  |  | 
|  | expect(storageDir.childFile('LOCK').existsSync(), true); | 
|  | expect(storageDir.childFile('LOCK').readAsBytesSync(), hasLength(0)); | 
|  |  | 
|  | expect(storageDir.childFile('LOG').existsSync(), true); | 
|  | expect(storageDir.childFile('LOG').readAsStringSync(), 'contents'); | 
|  | }); | 
|  | } | 
|  |  | 
|  | class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {} | 
|  |  | 
|  | Future<Chrome> testLaunchChrome(String userDataDir, FakeProcessManager processManager, ChromeLauncher chromeLauncher) { | 
|  | processManager.addCommand(FakeCommand( | 
|  | command: <String>[ | 
|  | 'example_chrome', | 
|  | '--user-data-dir=$userDataDir', | 
|  | '--remote-debugging-port=1234', | 
|  | ..._kChromeArgs, | 
|  | 'example_url', | 
|  | ], | 
|  | stderr: kDevtoolsStderr, | 
|  | )); | 
|  |  | 
|  | return chromeLauncher.launch( | 
|  | 'example_url', | 
|  | skipCheck: true, | 
|  | ); | 
|  | } |