Skip to content

Commit 8fcfc7a

Browse files
committed
Display a pause screen in a paused browser.
Closes #294. [email protected] Review URL: https://codereview.chromium.org//1264043002 .
1 parent 392544a commit 8fcfc7a

File tree

9 files changed

+14568
-14315
lines changed

9 files changed

+14568
-14315
lines changed

lib/src/runner.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,10 +238,10 @@ class Runner {
238238
"${suite.platform} and set breakpoints. Once you're finished, "
239239
"return to this terminal and press Enter."));
240240

241-
// TODO(nweiz): Display something in the paused browsers indicating that
242-
// they're paused.
243-
244-
await stdinLines.next;
241+
await race([
242+
suite.environment.displayPause(),
243+
cancelableNext(stdinLines)
244+
]);
245245
} finally {
246246
_reporter.resume();
247247
}

lib/src/runner/browser/browser_manager.dart

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import 'package:pool/pool.dart';
1212

1313
import '../../backend/metadata.dart';
1414
import '../../backend/test_platform.dart';
15+
import '../../util/cancelable_future.dart';
1516
import '../../util/multi_channel.dart';
1617
import '../../util/remote_exception.dart';
1718
import '../../util/stack_trace_mapper.dart';
@@ -52,6 +53,12 @@ class BrowserManager {
5253
/// Whether the channel to the browser has closed.
5354
bool _closed = false;
5455

56+
/// The completer for [_BrowserEnvironment.displayPause].
57+
///
58+
/// This will be `null` as long as the browser isn't displaying a pause
59+
/// screen.
60+
CancelableCompleter _pauseCompleter;
61+
5562
/// The environment to attach to each suite.
5663
_BrowserEnvironment _environment;
5764

@@ -62,7 +69,7 @@ class BrowserManager {
6269
webSocket.map(JSON.decode),
6370
mapSink(webSocket, JSON.encode)) {
6471
_environment = new _BrowserEnvironment(this);
65-
_channel.stream.listen(null, onDone: () => _closed = true);
72+
_channel.stream.listen(_onMessage, onDone: _onDone);
6673
}
6774

6875
/// Tells the browser the load a test suite from the URL [url].
@@ -153,6 +160,35 @@ class BrowserManager {
153160
}), platform: browser, metadata: metadata, path: path,
154161
onClose: () => closeIframe());
155162
}
163+
164+
/// An implementation of [Environment.displayPause].
165+
CancelableFuture _displayPause() {
166+
if (_pauseCompleter != null) return _pauseCompleter.future;
167+
168+
_pauseCompleter = new CancelableCompleter(() {
169+
_channel.sink.add({"command": "resume"});
170+
_pauseCompleter = null;
171+
});
172+
173+
_channel.sink.add({"command": "displayPause"});
174+
return _pauseCompleter.future.whenComplete(() {
175+
_pauseCompleter = null;
176+
});
177+
}
178+
179+
/// The callback for handling messages received from the host page.
180+
void _onMessage(Map message) {
181+
assert(message["command"] == "resume");
182+
if (_pauseCompleter == null) return;
183+
_pauseCompleter.complete();
184+
}
185+
186+
/// The callback called when the WebSocket is closed.
187+
void _onDone() {
188+
_closed = true;
189+
if (_pauseCompleter != null) _pauseCompleter.complete();
190+
_pauseCompleter = null;
191+
}
156192
}
157193

158194
/// An implementation of [Environment] for the browser.
@@ -162,4 +198,6 @@ class _BrowserEnvironment implements Environment {
162198
final BrowserManager _manager;
163199

164200
_BrowserEnvironment(this._manager);
201+
202+
CancelableFuture displayPause() => _manager._displayPause();
165203
}

lib/src/runner/browser/static/host.css

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,35 @@ iframe {
88
visibility: hidden;
99
}
1010

11+
#play {
12+
display: none;
13+
cursor: pointer;
14+
}
15+
16+
#dark {
17+
display: none;
18+
}
19+
20+
.paused #play {
21+
display: block;
22+
}
23+
24+
.paused #dark {
25+
display: block;
26+
position: absolute;
27+
width: 100%;
28+
height: 100%;
29+
top: 0;
30+
right: 0;
31+
background-color: rgba(0, 0, 0, 0.5);
32+
}
33+
34+
.paused #right-flank, .paused #right-ear, .paused #right-paw,
35+
.paused #left-flank, .paused #left-ear, .paused #left-paw {
36+
-webkit-animation-play-state: paused;
37+
animation-play-state: paused;
38+
}
39+
1140
/* Compiled output from
1241
* http://codepen.io/mknadler/pen/11b75cb014a3c382f54abf527655af21. */
1342

lib/src/runner/browser/static/host.dart

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,21 @@ void main() {
8181
var suiteChannel = serverChannel.virtualChannel(message['channel']);
8282
var iframeChannel = _connectToIframe(message['url'], message['id']);
8383
suiteChannel.pipe(iframeChannel);
84+
} else if (message['command'] == 'displayPause') {
85+
document.body.classes.add('paused');
86+
} else if (message['command'] == 'resume') {
87+
document.body.classes.remove('paused');
8488
} else {
8589
assert(message['command'] == 'closeSuite');
8690
_iframes[message['id']].remove();
8791
}
8892
});
93+
94+
var play = document.querySelector("#play");
95+
play.onClick.listen((_) {
96+
document.body.classes.remove('paused');
97+
serverChannel.sink.add({"command": "resume"});
98+
});
8999
}, onError: (error, stackTrace) {
90100
print("$error\n${new Trace.from(stackTrace).terse}");
91101
});
@@ -100,8 +110,9 @@ MultiChannel _connectToServer() {
100110
var webSocket = new WebSocket(currentUrl.queryParameters['managerUrl']);
101111

102112
var inputController = new StreamController(sync: true);
103-
webSocket.onMessage.listen(
104-
(message) => inputController.add(JSON.decode(message.data)));
113+
webSocket.onMessage.listen((message) {
114+
inputController.add(JSON.decode(message.data));
115+
});
105116

106117
var outputController = new StreamController(sync: true);
107118
outputController.stream.listen(

0 commit comments

Comments
 (0)