| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:async'; |
| import 'dart:sky' as sky; |
| import 'dart:sky.internals' as internals; |
| import 'dart:typed_data'; |
| |
| import 'package:mojo/core.dart' as core; |
| import 'package:mojo_services/mojo/asset_bundle/asset_bundle.mojom.dart'; |
| import 'package:sky/mojo/net/fetch.dart'; |
| import 'package:sky/mojo/net/image_cache.dart' as image_cache; |
| import 'package:sky/mojo/shell.dart' as shell; |
| |
| abstract class AssetBundle { |
| void close(); |
| Future<sky.Image> loadImage(String key); |
| Future<String> loadString(String key); |
| } |
| |
| class NetworkAssetBundle extends AssetBundle { |
| NetworkAssetBundle(Uri baseUrl) : _baseUrl = baseUrl; |
| |
| final Uri _baseUrl; |
| |
| void close() { } |
| |
| Future<sky.Image> loadImage(String key) { |
| return image_cache.load(_baseUrl.resolve(key).toString()); |
| } |
| |
| Future<String> loadString(String key) { |
| return fetchString(_baseUrl.resolve(key).toString()); |
| } |
| } |
| |
| Future _fetchAndUnpackBundle(String relativeUrl, AssetBundleProxy bundle) async { |
| core.MojoDataPipeConsumer bundleData = (await fetchUrl(relativeUrl)).body; |
| AssetUnpackerProxy unpacker = new AssetUnpackerProxy.unbound(); |
| shell.requestService("mojo:asset_bundle", unpacker); |
| unpacker.ptr.unpackZipStream(bundleData, bundle); |
| unpacker.close(); |
| } |
| |
| class MojoAssetBundle extends AssetBundle { |
| MojoAssetBundle(AssetBundleProxy this._bundle); |
| |
| factory MojoAssetBundle.fromNetwork(String relativeUrl) { |
| AssetBundleProxy bundle = new AssetBundleProxy.unbound(); |
| _fetchAndUnpackBundle(relativeUrl, bundle); |
| return new MojoAssetBundle(bundle); |
| } |
| |
| AssetBundleProxy _bundle; |
| Map<String, Future<sky.Image>> _imageCache = new Map<String, Future<sky.Image>>(); |
| Map<String, Future<String>> _stringCache = new Map<String, Future<String>>(); |
| |
| void close() { |
| _bundle.close(); |
| _bundle = null; |
| _imageCache = null; |
| } |
| |
| Future<sky.Image> loadImage(String key) { |
| return _imageCache.putIfAbsent(key, () { |
| Completer<sky.Image> completer = new Completer<sky.Image>(); |
| _bundle.ptr.getAsStream(key).then((response) { |
| new sky.ImageDecoder(response.assetData.handle.h, completer.complete); |
| }); |
| return completer.future; |
| }); |
| } |
| |
| Future<String> _fetchString(String key) async { |
| core.MojoDataPipeConsumer pipe = (await _bundle.ptr.getAsStream(key)).assetData; |
| ByteData data = await core.DataPipeDrainer.drainHandle(pipe); |
| return new String.fromCharCodes(new Uint8List.view(data.buffer)); |
| } |
| |
| Future<String> loadString(String key) { |
| return _stringCache.putIfAbsent(key, () => _fetchString(key)); |
| } |
| } |
| |
| AssetBundle _initRootBundle() { |
| try { |
| AssetBundleProxy bundle = new AssetBundleProxy.fromHandle( |
| new core.MojoHandle(internals.takeRootBundleHandle())); |
| return new MojoAssetBundle(bundle); |
| } catch (e) { |
| return null; |
| } |
| } |
| |
| final AssetBundle rootBundle = _initRootBundle(); |