Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ refactor: offline http cache #723

Merged
merged 11 commits into from
Oct 12, 2021
8 changes: 4 additions & 4 deletions integration_tests/lib/custom/custom_object_element.dart
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ class CustomObjectElement implements ObjectElementClient {
@override
void dispose() {
objectElementHost.updateChildTextureBox(null);
controller!.pause();
controller!.dispose();
controller?.pause();
controller?.dispose();
controller = null;
}

Expand All @@ -147,8 +147,8 @@ class CustomObjectElement implements ObjectElementClient {

@override
void didDetachRenderer() {
controller!.pause();
controller!.dispose();
controller?.pause();
controller?.dispose();
controller = null;
}

Expand Down
41 changes: 24 additions & 17 deletions kraken/lib/src/dom/elements/a.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,30 @@ class AnchorElement extends Element {
addEvent(EVENT_CLICK);
}

String get pathname {
if (_href != null) {
return Uri.parse(_href!).path;
} else {
return '';
}
}

@override
void handleMouseEvent(String eventType, { PointerDownEvent? down, PointerUpEvent? up }) {
super.handleMouseEvent(eventType, down: down, up: up);

String? href = _href;
if (href == null) return;

Uri uri = Uri.parse(href);
KrakenController rootController = elementManager.controller.view.rootController;
String? sourceUrl = rootController.bundleURL;
String scheme;
if (!uri.hasScheme) {
if (sourceUrl != null) {
Uri sourceUri = Uri.parse(sourceUrl);
scheme = sourceUri.scheme;
} else {
scheme = 'http';
}
} else {
scheme = uri.scheme;
if (href != null) {
String baseUrl = elementManager.controller.href;
Uri baseUri = Uri.parse(baseUrl);
Uri resolvedUri = elementManager.controller.uriParser!.resolve(baseUri, Uri.parse(href));
elementManager.controller.view.handleNavigationAction(
baseUrl, resolvedUri.toString(), _getNavigationType(resolvedUri.scheme));
}
elementManager.controller.view.handleNavigationAction(sourceUrl, href, _getNavigationType(scheme));
}

KrakenNavigationType _getNavigationType(String scheme) {
switch (scheme) {
switch (scheme.toLowerCase()) {
case 'http':
case 'https':
case 'file':
Expand All @@ -60,6 +58,15 @@ class AnchorElement extends Element {
return KrakenNavigationType.navigate;
}

@override
getProperty(String key) {
switch (key) {
case 'pathname':
return pathname;
}
return super.getProperty(key);
}

@override
void setProperty(String key, dynamic value) {
super.setProperty(key, value);
Expand Down
6 changes: 3 additions & 3 deletions kraken/lib/src/dom/elements/object.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ class ObjectElement extends Element implements ObjectElementHost {
_objectElementClient = _objectElementClientFactory(this);
}

Future<dynamic> initElementClient() async {
Future initElementClient() async {
try {
await _objectElementClient.initElementClient(properties);
} catch (e) {
print(e);
} catch (error, stackTrace) {
print('$error\n$stackTrace');
}
}

Expand Down
14 changes: 8 additions & 6 deletions kraken/lib/src/foundation/http_cache.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,19 @@ class HttpCacheController {

// Get the CacheObject by uri, no validation needed here.
Future<HttpCacheObject> getCacheObject(Uri uri) async {
HttpCacheObject cacheObject;

// L2 cache in memory.
final String key = _getCacheKey(uri);
if (_caches.containsKey(key)) {
return _caches[key]!;
cacheObject = _caches[key]!;
} else {
// Get cache in disk.
final int hash = key.hashCode;
final Directory cacheDirectory = await getCacheDirectory();
cacheObject = HttpCacheObject(key, cacheDirectory.path, hash: hash, origin: _origin);
}

// Get cache in disk.
final int hash = key.hashCode;
final Directory cacheDirectory = await getCacheDirectory();
HttpCacheObject cacheObject = HttpCacheObject(key, cacheDirectory.path, hash: hash, origin: _origin);

await cacheObject.read();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这两边的改动差了一个 cacheObject.read(); 的执行,原本是有问题还是说内存中的 cacheObject 原本不需要 read?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

下面有一行 read 去掉了, 统一到这里来; 原来的处理对于非缓存的情况会 read 两次, 虽然 read 函数里面有 valid 校验, 不会导致实际 io 两次, 但是改成这样更合理一些


return cacheObject;
Expand Down
39 changes: 29 additions & 10 deletions kraken/lib/src/foundation/http_cache_object.dart
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,13 @@ class HttpCacheObject {
bool isDateTimeValid() => expiredTime != null && expiredTime!.isAfter(DateTime.now());

// Validate the cache-control and expires.
Future<bool> hitLocalCache(HttpClientRequest request) async {
if (!valid) {
await read();
}
return isDateTimeValid();
bool hitLocalCache(HttpClientRequest request) {
return valid && isDateTimeValid();
}

/// Read the index file.
Future<void> read() async {
if (_valid) return;
final bool isIndexFileExist = await _file.exists();
if (!isIndexFileExist) {
// Index file not exist, dispose.
Expand Down Expand Up @@ -173,6 +171,12 @@ class HttpCacheObject {
contentLength = byteData.getUint32(index, Endian.little);
index += 4;

// Invalid cache blob size, mark as invalid.
if (await _blob.length != contentLength) {
_valid = false;
return;
}

// Read url.
int urlLength = byteData.getUint32(index, Endian.little);
index += 4;
Expand Down Expand Up @@ -243,10 +247,11 @@ class HttpCacheObject {

// Remove all the cached files.
Future<void> remove() async {
await Future.wait([
_file.delete(),
_blob.remove(),
]);
if (await _file.exists()) {
await _file.delete();
}
await _blob.remove();

_valid = false;
}

Expand Down Expand Up @@ -350,6 +355,15 @@ class HttpCacheObjectBlob extends EventSink<List<int>> {

HttpCacheObjectBlob(this.path) : _file = File(path);

// The length of the file.
Future<int> get length async {
if (await exists()) {
return await _file.length();
} else {
return 0;
}
}

@override
void add(List<int> data) {
_writer ??= _file.openWrite();
Expand All @@ -370,6 +384,8 @@ class HttpCacheObjectBlob extends EventSink<List<int>> {
// Ensure buffer has been written.
await _writer?.flush();
await _writer?.close();

_writer = null;
}

Future<bool> exists() {
Expand All @@ -381,6 +397,9 @@ class HttpCacheObjectBlob extends EventSink<List<int>> {
}

Future<void> remove() async {
await _file.delete();
if (await _file.exists()) {
await _file.delete();
}
close();
}
}
Loading