Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions dwds/debug_extension/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: extension
publish_to: none
version: 1.0.0
author: Dart Team <misc@dartlang.org>
homepage: https://github.com/dart-lang/webdev
description: >-
A chrome extension for Dart debugging.

environment:
sdk: ">=2.3.2-dev.0.1 <3.0.0"

dependencies:
js: ^0.6.1+1
sse: ^2.0.2

dev_dependencies:
webdev: ^2.0.0
build_web_compilers: ">=1.2.0 <3.0.0"
build_runner: ">=1.5.0 <2.0.0"
112 changes: 112 additions & 0 deletions dwds/debug_extension/web/background.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

@JS('chrome')
library background;

import 'package:js/js.dart';
import 'package:sse/client/sse_client.dart';

// GENERATE:
// pub run build_runner build web -o build -r
void main() {
addListener(allowInterop((e) {
var query = QueryInfo(active: true, currentWindow: true);
Tab currentTab;

// Sends commands to debugger attached to the current tab.
//
// Extracts the extension backend port from the injected JS.
var callback = allowInterop((List<Tab> tabs) {
currentTab = tabs[0];
attach(Debuggee(tabId: currentTab.id), '1.3', allowInterop(() {}));
sendCommand(Debuggee(tabId: currentTab.id), 'Debugger.enable',
CommandParams(), allowInterop((e) {}));
sendCommand(Debuggee(tabId: currentTab.id), 'Runtime.evaluate',
CommandParams(expression: '\$extensionPort'),
allowInterop((RemoteObject e) {
var port = e.result.value;
startSseClient(port);
}));
});

queryTabs(query, allowInterop((List tabs) {
callback(List.from(tabs));
}));
}));
}

// Starts an SSE client.
//
// Creates 2 channels which connect to the SSE handler at the extension
// backend, send a simple message.
Future<void> startSseClient(port) async {
var channel = SseClient('http://localhost:$port/test');
channel.stream.listen((s) {
channel.sink.add('This is channel 1.');
}, onError: (e) {
channel.close();
}, cancelOnError: true);

var channel2 = SseClient('http://localhost:$port/test');
await channel2.onOpen.first;
channel2.sink.add('This is channel 2.');
}

@JS('browserAction.onClicked.addListener')
external void addListener(Function callback);

@JS('debugger.sendCommand')
external void sendCommand(Debuggee target, String method,
CommandParams commandParams, Function callback);

@JS('debugger.attach')
external void attach(
Debuggee target, String requiredVersion, Function callback);

@JS('tabs.query')
external void queryTabs(QueryInfo queryInfo, Function callback);

@JS()
@anonymous
class QueryInfo {
external bool get active;
external bool get currentWindow;
external factory QueryInfo({bool active, bool currentWindow});
}

@JS()
@anonymous
class Debuggee {
external dynamic get tabId;
external String get extensionId;
external String get targetId;
external factory Debuggee(
{dynamic tabId, String extensionId, String targetId});
}

@JS()
@anonymous
class CommandParams {
external String get expression;
external factory CommandParams({String expression});
}

@JS()
@anonymous
class Tab {
external int get id;
}

@JS()
@anonymous
class RemoteObject {
external EvaluationResult get result;
}

@JS()
@anonymous
class EvaluationResult {
external dynamic get value;
}
Loading