[web] Add canUpdateAsMatch to PersistedPlatformView. (flutter/engine#21313)

This commit is contained in:
David Iglesias 2020-09-23 21:47:02 -07:00 committed by GitHub
parent 972e469ebd
commit 6d83eaebe2
5 changed files with 102 additions and 22 deletions

View File

@ -5,7 +5,6 @@
// @dart = 2.6
import 'dart:io' as io;
import 'package:meta/meta.dart';
import 'package:path/path.dart' as pathlib;
import 'package:web_driver_installer/chrome_driver_installer.dart';
import 'package:web_driver_installer/firefox_driver_installer.dart';
@ -184,14 +183,12 @@ class SafariDriverManager extends DriverManager {
/// tests.
abstract class DriverManager {
/// Installation directory for browser's driver.
@protected
final io.Directory _browserDriverDir;
/// This is the parent directory for all drivers.
///
/// This directory is saved to [temporaryDirectories] and deleted before
/// tests shutdown.
@protected
final io.Directory _drivers;
DriverManager(String browser)
@ -223,7 +220,6 @@ abstract class DriverManager {
Future<void> _verifyDriverForLUCI();
@protected
Future<void> _startDriver();
static DriverManager chooseDriver(String browser) {

View File

@ -88,16 +88,13 @@ abstract class BrowserHistory {
///
/// Subclasses should send appropriate system messages to update the flutter
/// applications accordingly.
@protected
void onPopState(covariant html.PopStateEvent event);
/// Sets up any prerequisites to use this browser history class.
@protected
Future<void> setup() => Future<void>.value();
/// Restore any modifications to the html browser history during the lifetime
/// of this class.
@protected
Future<void> tearDown() => Future<void>.value();
}

View File

@ -75,6 +75,16 @@ class PersistedPlatformView extends PersistedLeafSurface {
}
}
// Platform Views can only be updated if their viewId matches.
@override
bool canUpdateAsMatch(PersistedSurface oldSurface) {
if (super.canUpdateAsMatch(oldSurface)) {
// super checks the runtimeType of the surface, so we can just cast...
return viewId == ((oldSurface as PersistedPlatformView).viewId);
}
return false;
}
@override
double matchForUpdate(PersistedPlatformView existingSurface) {
return existingSurface.viewId == viewId ? 0.0 : 1.0;
@ -82,11 +92,10 @@ class PersistedPlatformView extends PersistedLeafSurface {
@override
void update(PersistedPlatformView oldSurface) {
assert(viewId == oldSurface.viewId, 'PersistedPlatformView with different viewId should never be updated. Check the canUpdateAsMatch method.',);
super.update(oldSurface);
if (viewId != oldSurface.viewId) {
// The content of the surface has to be rebuild if the viewId is changed.
build();
} else if (dx != oldSurface.dx ||
// Only update if the view has been resized
if (dx != oldSurface.dx ||
dy != oldSurface.dy ||
width != oldSurface.width ||
height != oldSurface.height) {

View File

@ -275,7 +275,6 @@ abstract class PersistedSurface implements ui.EngineLayer {
/// retain came in.
@mustCallSuper
@visibleForTesting
@protected
void revive() {
assert(debugAssertSurfaceState(this, PersistedSurfaceState.released));
state = PersistedSurfaceState.created;
@ -304,6 +303,7 @@ abstract class PersistedSurface implements ui.EngineLayer {
html.Element? rootElement;
/// Whether this surface can update an existing [oldSurface].
@mustCallSuper
bool canUpdateAsMatch(PersistedSurface oldSurface) {
return oldSurface.isActive && runtimeType == oldSurface.runtimeType;
}
@ -342,7 +342,6 @@ abstract class PersistedSurface implements ui.EngineLayer {
///
/// This is called when we failed to locate an existing DOM element to reuse,
/// such as on the very first frame.
@protected
@mustCallSuper
void build() {
if (rootElement != null) {
@ -371,7 +370,6 @@ abstract class PersistedSurface implements ui.EngineLayer {
/// frame, we reuse old ones as much as possible. This method should only be
/// called when [isTotalMatchFor] returns true for the [oldSurface]. Otherwise
/// adopting the [oldSurface]'s elements could lead to correctness issues.
@protected
@mustCallSuper
void adoptElements(covariant PersistedSurface oldSurface) {
assert(oldSurface.rootElement != null);
@ -399,7 +397,6 @@ abstract class PersistedSurface implements ui.EngineLayer {
///
/// Attempts to reuse [oldSurface]'s DOM element, if possible. Otherwise,
/// creates a new element by calling [build].
@protected
@mustCallSuper
void update(covariant PersistedSurface oldSurface) {
assert(oldSurface != null); // ignore: unnecessary_null_comparison
@ -424,7 +421,6 @@ abstract class PersistedSurface implements ui.EngineLayer {
///
/// This is also different from [build], which constructs a brand new surface
/// sub-tree.
@protected
@mustCallSuper
void retain() {
assert(rootElement != null);
@ -448,7 +444,6 @@ abstract class PersistedSurface implements ui.EngineLayer {
///
/// This method may be overridden by concrete implementations, for example, to
/// recycle the resources owned by this surface.
@protected
@mustCallSuper
void discard() {
assert(debugAssertSurfaceState(this, PersistedSurfaceState.active));
@ -471,7 +466,6 @@ abstract class PersistedSurface implements ui.EngineLayer {
state = PersistedSurfaceState.released;
}
@protected
@mustCallSuper
void debugValidate(List<String> validationErrors) {
if (rootElement == null) {
@ -541,7 +535,6 @@ abstract class PersistedSurface implements ui.EngineLayer {
/// clip behaviors.
///
/// This method is called by the [preroll] method.
@protected
void recomputeTransformAndClip() {
_transform = parent!._transform;
_localClipBounds = null;
@ -578,7 +571,6 @@ abstract class PersistedSurface implements ui.EngineLayer {
}
}
@protected
@mustCallSuper
void debugPrintAttributes(StringBuffer buffer) {
if (rootElement != null) {
@ -586,7 +578,6 @@ abstract class PersistedSurface implements ui.EngineLayer {
}
}
@protected
@mustCallSuper
void debugPrintChildren(StringBuffer buffer, int indent) {}
@ -1155,7 +1146,6 @@ abstract class PersistedContainerSurface extends PersistedSurface {
}
@override
@protected
@mustCallSuper
void debugValidate(List<String> validationErrors) {
super.debugValidate(validationErrors);

View File

@ -0,0 +1,88 @@
// Copyright 2013 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.
// @dart = 2.6
import 'dart:async';
import 'dart:html' as html;
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart';
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import '../../matchers.dart';
const MethodCodec codec = StandardMethodCodec();
final EngineWindow window = EngineWindow();
void main() {
internalBootstrapBrowserTest(() => testMain);
}
void testMain() {
PersistedPlatformView view;
group('PersistedPlatformView', () {
setUp(() async {
platformViewRegistry.registerViewFactory(
'test-0',
(viewId) => html.DivElement(),
);
platformViewRegistry.registerViewFactory(
'test-1',
(viewId) => html.DivElement(),
);
// Ensure the views are created...
await Future.wait([
_createPlatformView(0, 'test-0'),
_createPlatformView(1, 'test-1'),
]);
view = PersistedPlatformView(0, 0, 0, 100, 100)..build();
});
group('update', () {
test('throws assertion error if called with different viewIds', () {
final differentView = PersistedPlatformView(1, 1, 1, 100, 100)..build();
expect(() {
view.update(differentView);
}, throwsAssertionError);
});
});
group('canUpdateAsMatch', () {
test('returns true when viewId is the same', () {
final sameView = PersistedPlatformView(0, 1, 1, 100, 100)..build();
expect(view.canUpdateAsMatch(sameView), isTrue);
});
test('returns false when viewId is different', () {
final differentView = PersistedPlatformView(1, 1, 1, 100, 100)..build();
expect(view.canUpdateAsMatch(differentView), isFalse);
});
test('returns false when other view is not a PlatformView', () {
final anyView = PersistedOpacity(null, 1, Offset(0, 0))..build();
expect(view.canUpdateAsMatch(anyView), isFalse);
});
});
});
}
// Sends a platform message to create a Platform View with the given id and viewType.
Future<void> _createPlatformView(int id, String viewType) {
final completer = Completer<void>();
window.sendPlatformMessage(
'flutter/platform_views',
codec.encodeMethodCall(MethodCall(
'create',
<String, dynamic>{
'id': id,
'viewType': viewType,
},
)),
(dynamic _) => completer.complete(),
);
return completer.future;
}