[simple_browser] Add support for popup windows.
Spawns new Simple Browser tabs for browser popups.
Test: Used Gaia login, Drive features which require popups.
Bug: 29938
Change-Id: I27092480b4ec125e9065ddc863e3b832dc2b06b9
diff --git a/bin/simple_browser/lib/main.dart b/bin/simple_browser/lib/main.dart
index c9b34d8..21ecc0f 100644
--- a/bin/simple_browser/lib/main.dart
+++ b/bin/simple_browser/lib/main.dart
@@ -36,8 +36,15 @@
void main() {
setupLogger(name: 'Browser');
final _context = ChromiumWebView.createContext();
- final tabsBloc = TabsBloc(
- tabFactory: () => WebPageBloc(context: _context),
+
+ // Bind |tabsBloc| here so that it can be referenced in the TabsBloc
+ // constructor arguments.
+ TabsBloc<WebPageBloc> tabsBloc;
+ tabsBloc = TabsBloc(
+ tabFactory: () => WebPageBloc(
+ context: _context,
+ popupHandler: (tab) =>
+ tabsBloc.request.add(AddTabAction<WebPageBloc>(tab: tab))),
disposeTab: (tab) {
tab.dispose();
},
diff --git a/bin/simple_browser/lib/src/blocs/tabs_bloc.dart b/bin/simple_browser/lib/src/blocs/tabs_bloc.dart
index f10d4ba..56ff52b 100644
--- a/bin/simple_browser/lib/src/blocs/tabs_bloc.dart
+++ b/bin/simple_browser/lib/src/blocs/tabs_bloc.dart
@@ -76,6 +76,12 @@
_tabs.value = UnmodifiableListView<T>(_tabsList);
disposeTab(tab);
break;
+ case TabsActionType.addTab:
+ final AddTabAction<T> addTabAction = action;
+ _tabsList.add(addTabAction.tab);
+ _tabs.value = UnmodifiableListView<T>(_tabsList);
+ _currentTab.value = addTabAction.tab;
+ break;
}
}
}
diff --git a/bin/simple_browser/lib/src/blocs/webpage_bloc.dart b/bin/simple_browser/lib/src/blocs/webpage_bloc.dart
index e2cf673..0859574 100644
--- a/bin/simple_browser/lib/src/blocs/webpage_bloc.dart
+++ b/bin/simple_browser/lib/src/blocs/webpage_bloc.dart
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'dart:async';
+import 'package:fidl/fidl.dart' show InterfaceHandle;
import 'package:flutter/foundation.dart';
import 'package:fuchsia_logger/logger.dart';
import 'package:fuchsia_scenic_flutter/child_view.dart'
@@ -33,6 +34,7 @@
// isLoadedState: bool indicating whether main document has fully loaded.
class WebPageBloc extends web.NavigationEventListener {
final ChromiumWebView _webView;
+ final _PopupListener _popupListener;
ChildViewConnection get childViewConnection => _webView.childViewConnection;
@@ -65,8 +67,12 @@
WebPageBloc({
String homePage,
web.ContextProxy context,
- }) : _webView = ChromiumWebView.withContext(context: context) {
- _webView.setNavigationEventListener(this);
+ void Function(WebPageBloc popup) popupHandler,
+ }) : _webView = ChromiumWebView.withContext(context: context),
+ _popupListener = _PopupListener(popupHandler) {
+ _webView
+ ..setNavigationEventListener(this)
+ ..setPopupFrameCreationListener(_popupListener);
if (homePage != null) {
_handleAction(NavigateToAction(url: homePage));
@@ -74,6 +80,18 @@
_webPageActionController.stream.listen(_handleAction);
}
+ WebPageBloc.withFrame({
+ @required web.FrameProxy frame,
+ void Function(WebPageBloc popup) popupHandler,
+ }) : _webView = ChromiumWebView.withFrame(frame: frame),
+ _popupListener = _PopupListener(popupHandler) {
+ _webView
+ ..setNavigationEventListener(this)
+ ..setPopupFrameCreationListener(_popupListener);
+
+ _webPageActionController.stream.listen(_handleAction);
+ }
+
void dispose() {
_webView.dispose();
_webPageActionController.close();
@@ -132,3 +150,18 @@
}
}
}
+
+class _PopupListener extends web.PopupFrameCreationListener {
+ final void Function(WebPageBloc popup) _handler;
+
+ _PopupListener(handler) : _handler = handler;
+
+ @override
+ Future<void> onPopupFrameCreated(
+ InterfaceHandle<web.Frame> frame,
+ web.PopupFrameCreationInfo info,
+ ) async {
+ _handler(WebPageBloc.withFrame(
+ frame: web.FrameProxy()..ctrl.bind(frame), popupHandler: _handler));
+ }
+}
diff --git a/bin/simple_browser/lib/src/models/tabs_action.dart b/bin/simple_browser/lib/src/models/tabs_action.dart
index f7123ba..cfc8ad2 100644
--- a/bin/simple_browser/lib/src/models/tabs_action.dart
+++ b/bin/simple_browser/lib/src/models/tabs_action.dart
@@ -11,7 +11,7 @@
}
// Operations allowed for tab management
-enum TabsActionType { newTab, removeTab, focusTab }
+enum TabsActionType { newTab, removeTab, focusTab, addTab }
// Instructs to add a new tab to tab list.
class NewTabAction<T> extends TabsAction<T> {
@@ -29,3 +29,9 @@
final T tab;
const FocusTabAction({@required this.tab}) : super(TabsActionType.focusTab);
}
+
+// Instructs to add an existing tab to the tab list.
+class AddTabAction<T> extends TabsAction<T> {
+ final T tab;
+ const AddTabAction({@required this.tab}) : super(TabsActionType.addTab);
+}