Make it possible to run Sky apps offline
This CL makes it possible to run Sky apps offline by introducing new DartLibraryProvider subclasses, specifically one that can load directly from the file system. A future CL will expand this functionality to work with asset bundles as well. Currently, the only platform that uses this functionality is Linux, which can now load a simple Sky app without even loading a network stack. Making this work on other platforms is work for future CLs. TBR=eseidel@chromium.org Review URL: https://codereview.chromium.org/1203143004.
This commit is contained in:
parent
4dbf8152e7
commit
21c9976f78
@ -21,6 +21,7 @@ common_deps = [
|
||||
"//sky/engine/wtf",
|
||||
"//sky/services/platform",
|
||||
"//sky/services/viewport",
|
||||
"//sky/shell/dart",
|
||||
"//ui/gfx/geometry",
|
||||
"//ui/gl",
|
||||
]
|
||||
|
@ -183,7 +183,7 @@ public class PlatformViewAndroid extends SurfaceView
|
||||
}
|
||||
|
||||
public void loadUrl(String url) {
|
||||
mViewportObserver.loadUrl(url);
|
||||
mViewportObserver.runFromNetwork(url);
|
||||
}
|
||||
|
||||
private void attach() {
|
||||
|
24
engine/src/flutter/shell/dart/BUILD.gn
Normal file
24
engine/src/flutter/shell/dart/BUILD.gn
Normal file
@ -0,0 +1,24 @@
|
||||
# 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.
|
||||
|
||||
source_set("dart") {
|
||||
sources = [
|
||||
"dart_library_provider_files.cc",
|
||||
"dart_library_provider_files.h",
|
||||
"dart_library_provider_network.cc",
|
||||
"dart_library_provider_network.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//base",
|
||||
"//build/config/sanitizers:deps",
|
||||
"//dart/runtime:libdart",
|
||||
"//mojo/common",
|
||||
"//mojo/public/cpp/application",
|
||||
"//mojo/services/network/public/interfaces",
|
||||
"//sky/engine/tonic",
|
||||
"//sky/engine/wtf",
|
||||
"//url",
|
||||
]
|
||||
}
|
78
engine/src/flutter/shell/dart/dart_library_provider_files.cc
Normal file
78
engine/src/flutter/shell/dart/dart_library_provider_files.cc
Normal file
@ -0,0 +1,78 @@
|
||||
// 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.
|
||||
|
||||
#include "sky/shell/dart/dart_library_provider_files.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/threading/worker_pool.h"
|
||||
#include "mojo/common/data_pipe_utils.h"
|
||||
#include "sky/engine/tonic/dart_converter.h"
|
||||
|
||||
namespace sky {
|
||||
namespace shell {
|
||||
namespace {
|
||||
|
||||
void Ignored(bool) {
|
||||
}
|
||||
|
||||
base::FilePath SimplifyPath(const base::FilePath& path) {
|
||||
std::vector<base::FilePath::StringType> components;
|
||||
path.GetComponents(&components);
|
||||
base::FilePath result;
|
||||
for (const auto& component : components) {
|
||||
if (component == base::FilePath::kCurrentDirectory)
|
||||
continue;
|
||||
if (component == base::FilePath::kParentDirectory)
|
||||
result = result.DirName();
|
||||
else
|
||||
result = result.Append(component);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
DartLibraryProviderFiles::DartLibraryProviderFiles(
|
||||
const base::FilePath& package_root)
|
||||
: package_root_(package_root) {
|
||||
}
|
||||
|
||||
DartLibraryProviderFiles::~DartLibraryProviderFiles() {
|
||||
}
|
||||
|
||||
void DartLibraryProviderFiles::GetLibraryAsStream(
|
||||
const String& name,
|
||||
blink::DataPipeConsumerCallback callback) {
|
||||
mojo::DataPipe pipe;
|
||||
callback.Run(pipe.consumer_handle.Pass());
|
||||
|
||||
base::FilePath source(name.toUTF8());
|
||||
scoped_refptr<base::TaskRunner> runner =
|
||||
base::WorkerPool::GetTaskRunner(true);
|
||||
mojo::common::CopyFromFile(source, pipe.producer_handle.Pass(), 0,
|
||||
runner.get(), base::Bind(&Ignored));
|
||||
}
|
||||
|
||||
std::string DartLibraryProviderFiles::CanonicalizePackageURL(std::string url) {
|
||||
DCHECK(StartsWithASCII(url, "package:", true));
|
||||
ReplaceFirstSubstringAfterOffset(&url, 0, "package:", "");
|
||||
return package_root_.Append(url).AsUTF8Unsafe();
|
||||
}
|
||||
|
||||
Dart_Handle DartLibraryProviderFiles::CanonicalizeURL(Dart_Handle library,
|
||||
Dart_Handle url) {
|
||||
std::string string = blink::StdStringFromDart(url);
|
||||
if (StartsWithASCII(string, "dart:", true))
|
||||
return url;
|
||||
if (StartsWithASCII(string, "package:", true))
|
||||
return blink::StdStringToDart(CanonicalizePackageURL(string));
|
||||
base::FilePath base_path(blink::StdStringFromDart(Dart_LibraryUrl(library)));
|
||||
base::FilePath resolved_path = base_path.DirName().Append(string);
|
||||
base::FilePath normalized_path = SimplifyPath(resolved_path);
|
||||
return blink::StdStringToDart(normalized_path.AsUTF8Unsafe());
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
} // namespace sky
|
36
engine/src/flutter/shell/dart/dart_library_provider_files.h
Normal file
36
engine/src/flutter/shell/dart/dart_library_provider_files.h
Normal file
@ -0,0 +1,36 @@
|
||||
// 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.
|
||||
|
||||
#ifndef SKY_SHELL_DART_DART_LIBRARY_PROVIDER_FILES_H_
|
||||
#define SKY_SHELL_DART_DART_LIBRARY_PROVIDER_FILES_H_
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "sky/engine/tonic/dart_library_provider.h"
|
||||
|
||||
namespace sky {
|
||||
namespace shell {
|
||||
|
||||
class DartLibraryProviderFiles : public blink::DartLibraryProvider {
|
||||
public:
|
||||
explicit DartLibraryProviderFiles(const base::FilePath& package_root);
|
||||
~DartLibraryProviderFiles() override;
|
||||
|
||||
protected:
|
||||
// |DartLibraryProvider| implementation:
|
||||
void GetLibraryAsStream(const String& name,
|
||||
blink::DataPipeConsumerCallback callback) override;
|
||||
Dart_Handle CanonicalizeURL(Dart_Handle library, Dart_Handle url) override;
|
||||
|
||||
private:
|
||||
std::string CanonicalizePackageURL(std::string url);
|
||||
|
||||
base::FilePath package_root_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DartLibraryProviderFiles);
|
||||
};
|
||||
|
||||
} // namespace shell
|
||||
} // namespace sky
|
||||
|
||||
#endif // SKY_SHELL_DART_DART_LIBRARY_PROVIDER_FILES_H_
|
@ -0,0 +1,88 @@
|
||||
// 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.
|
||||
|
||||
#include "sky/shell/dart/dart_library_provider_network.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "sky/engine/tonic/dart_converter.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace sky {
|
||||
namespace shell {
|
||||
namespace {
|
||||
|
||||
mojo::URLLoaderPtr Fetch(mojo::NetworkService* network_service,
|
||||
const String& url,
|
||||
base::Callback<void(mojo::URLResponsePtr)> callback) {
|
||||
mojo::URLLoaderPtr loader;
|
||||
network_service->CreateURLLoader(GetProxy(&loader));
|
||||
|
||||
mojo::URLRequestPtr request = mojo::URLRequest::New();
|
||||
request->url = url.toUTF8();
|
||||
request->auto_follow_redirects = true;
|
||||
loader->Start(request.Pass(), callback);
|
||||
|
||||
return loader.Pass();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class DartLibraryProviderNetwork::Job {
|
||||
public:
|
||||
Job(DartLibraryProviderNetwork* provider,
|
||||
const String& name,
|
||||
blink::DataPipeConsumerCallback callback)
|
||||
: provider_(provider), callback_(callback), weak_factory_(this) {
|
||||
url_loader_ =
|
||||
Fetch(provider_->network_service(), name,
|
||||
base::Bind(&Job::OnReceivedResponse, weak_factory_.GetWeakPtr()));
|
||||
}
|
||||
|
||||
private:
|
||||
void OnReceivedResponse(mojo::URLResponsePtr response) {
|
||||
mojo::ScopedDataPipeConsumerHandle data;
|
||||
if (response->status_code == 200)
|
||||
data = response->body.Pass();
|
||||
callback_.Run(data.Pass());
|
||||
provider_->jobs_.remove(this);
|
||||
// We're deleted now.
|
||||
}
|
||||
|
||||
DartLibraryProviderNetwork* provider_;
|
||||
blink::DataPipeConsumerCallback callback_;
|
||||
mojo::URLLoaderPtr url_loader_;
|
||||
|
||||
base::WeakPtrFactory<Job> weak_factory_;
|
||||
};
|
||||
|
||||
DartLibraryProviderNetwork::DartLibraryProviderNetwork(
|
||||
mojo::NetworkService* network_service)
|
||||
: network_service_(network_service) {
|
||||
}
|
||||
|
||||
DartLibraryProviderNetwork::~DartLibraryProviderNetwork() {
|
||||
}
|
||||
|
||||
void DartLibraryProviderNetwork::GetLibraryAsStream(
|
||||
const String& name,
|
||||
blink::DataPipeConsumerCallback callback) {
|
||||
jobs_.add(adoptPtr(new Job(this, name, callback)));
|
||||
}
|
||||
|
||||
Dart_Handle DartLibraryProviderNetwork::CanonicalizeURL(Dart_Handle library,
|
||||
Dart_Handle url) {
|
||||
std::string string = blink::StdStringFromDart(url);
|
||||
if (StartsWithASCII(string, "dart:", true))
|
||||
return url;
|
||||
// TODO(abarth): The package root should be configurable.
|
||||
if (StartsWithASCII(string, "package:", true))
|
||||
ReplaceFirstSubstringAfterOffset(&string, 0, "package:", "/packages/");
|
||||
GURL library_url(blink::StdStringFromDart(Dart_LibraryUrl(library)));
|
||||
GURL resolved_url = library_url.Resolve(string);
|
||||
return blink::StdStringToDart(resolved_url.spec());
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
} // namespace sky
|
@ -0,0 +1,41 @@
|
||||
// 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.
|
||||
|
||||
#ifndef SKY_SHELL_DART_DART_LIBRARY_PROVIDER_NETWORK_H_
|
||||
#define SKY_SHELL_DART_DART_LIBRARY_PROVIDER_NETWORK_H_
|
||||
|
||||
#include "mojo/services/network/public/interfaces/network_service.mojom.h"
|
||||
#include "sky/engine/tonic/dart_library_provider.h"
|
||||
#include "sky/engine/wtf/HashSet.h"
|
||||
#include "sky/engine/wtf/OwnPtr.h"
|
||||
|
||||
namespace sky {
|
||||
namespace shell {
|
||||
|
||||
class DartLibraryProviderNetwork : public blink::DartLibraryProvider {
|
||||
public:
|
||||
explicit DartLibraryProviderNetwork(mojo::NetworkService* network_service);
|
||||
~DartLibraryProviderNetwork() override;
|
||||
|
||||
mojo::NetworkService* network_service() const { return network_service_; }
|
||||
|
||||
protected:
|
||||
// |DartLibraryProvider| implementation:
|
||||
void GetLibraryAsStream(const String& name,
|
||||
blink::DataPipeConsumerCallback callback) override;
|
||||
Dart_Handle CanonicalizeURL(Dart_Handle library, Dart_Handle url) override;
|
||||
|
||||
private:
|
||||
class Job;
|
||||
|
||||
mojo::NetworkService* network_service_;
|
||||
HashSet<OwnPtr<Job>> jobs_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DartLibraryProviderNetwork);
|
||||
};
|
||||
|
||||
} // namespace shell
|
||||
} // namespace sky
|
||||
|
||||
#endif // SKY_SHELL_DART_DART_LIBRARY_PROVIDER_NETWORK_H_
|
@ -131,7 +131,7 @@ static sky::InputEventPtr BasicInputEventFromRecognizer(
|
||||
self.platformView->ConnectToViewportObserver(interface_request.Pass());
|
||||
|
||||
mojo::String string(self.skyInitialLoadURL.UTF8String);
|
||||
_viewport_observer->LoadURL(string);
|
||||
_viewport_observer->RunFromNetwork(string);
|
||||
}
|
||||
|
||||
- (void)notifySurfaceDestruction {
|
||||
|
@ -17,6 +17,9 @@
|
||||
namespace sky {
|
||||
namespace shell {
|
||||
|
||||
const char kMain[] = "main";
|
||||
const char kPackageRoot[] = "package-root";
|
||||
|
||||
void Init() {
|
||||
Shell::Init(make_scoped_ptr(new ServiceProviderContext(
|
||||
base::MessageLoop::current()->task_runner())));
|
||||
@ -27,8 +30,12 @@ void Init() {
|
||||
ViewportObserverPtr viewport_observer;
|
||||
shell_view->view()->ConnectToViewportObserver(GetProxy(&viewport_observer));
|
||||
|
||||
// TODO(abarth): At this point we should load some content into the view.
|
||||
// viewport_observer->LoadURL("https://domokit.github.io/home.dart");
|
||||
base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
|
||||
|
||||
std::string main = command_line.GetSwitchValueASCII(kMain);
|
||||
std::string package_root = command_line.GetSwitchValueASCII(kPackageRoot);
|
||||
|
||||
viewport_observer->RunFromFile(main, package_root);
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "sky/engine/public/web/WebSettings.h"
|
||||
#include "sky/engine/public/web/WebView.h"
|
||||
#include "sky/services/platform/platform_impl.h"
|
||||
#include "sky/shell/dart/dart_library_provider_files.h"
|
||||
#include "sky/shell/dart/dart_library_provider_network.h"
|
||||
#include "sky/shell/service_provider.h"
|
||||
#include "sky/shell/ui/animator.h"
|
||||
#include "sky/shell/ui/input_event_converter.h"
|
||||
@ -184,18 +186,45 @@ void Engine::OnInputEvent(InputEventPtr event) {
|
||||
web_view_->handleInputEvent(*web_event);
|
||||
}
|
||||
|
||||
void Engine::LoadURL(const mojo::String& mojo_url) {
|
||||
GURL url(mojo_url);
|
||||
if (!blink::WebView::shouldUseWebView(url)) {
|
||||
if (web_view_) {
|
||||
web_view_->close();
|
||||
web_view_ = nullptr;
|
||||
}
|
||||
sky_view_ = blink::SkyView::Create(this);
|
||||
sky_view_->Load(url);
|
||||
UpdateSkyViewSize();
|
||||
void Engine::CloseWebViewIfNeeded() {
|
||||
if (web_view_) {
|
||||
web_view_->close();
|
||||
web_view_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::RunFromLibrary(const mojo::String& name) {
|
||||
CloseWebViewIfNeeded();
|
||||
sky_view_ = blink::SkyView::Create(this);
|
||||
sky_view_->RunFromLibrary(blink::WebString::fromUTF8(name),
|
||||
dart_library_provider_.get());
|
||||
UpdateSkyViewSize();
|
||||
}
|
||||
|
||||
void Engine::RunFromNetwork(const mojo::String& url) {
|
||||
if (blink::WebView::shouldUseWebView(GURL(url))) {
|
||||
LoadUsingWebView(url);
|
||||
return;
|
||||
}
|
||||
dart_library_provider_.reset(
|
||||
new DartLibraryProviderNetwork(g_platform_impl->networkService()));
|
||||
RunFromLibrary(url);
|
||||
}
|
||||
|
||||
void Engine::RunFromFile(const mojo::String& main,
|
||||
const mojo::String& package_root) {
|
||||
dart_library_provider_.reset(
|
||||
new DartLibraryProviderFiles(base::FilePath(package_root)));
|
||||
RunFromLibrary(main);
|
||||
}
|
||||
|
||||
void Engine::RunFromSnapshot(mojo::ScopedDataPipeConsumerHandle snapshot) {
|
||||
// TODO(abarth): Implement.
|
||||
}
|
||||
|
||||
void Engine::LoadUsingWebView(const mojo::String& mojo_url) {
|
||||
GURL url(mojo_url);
|
||||
DCHECK(blink::WebView::shouldUseWebView(url));
|
||||
|
||||
if (sky_view_)
|
||||
sky_view_ = nullptr;
|
||||
@ -250,8 +279,9 @@ mojo::NavigatorHost* Engine::NavigatorHost() {
|
||||
void Engine::RequestNavigate(mojo::Target target,
|
||||
mojo::URLRequestPtr request) {
|
||||
// Ignoring target for now.
|
||||
base::MessageLoop::current()->PostTask(FROM_HERE,
|
||||
base::Bind(&Engine::LoadURL, GetWeakPtr(), request->url));
|
||||
base::MessageLoop::current()->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&Engine::RunFromNetwork, GetWeakPtr(), request->url));
|
||||
}
|
||||
|
||||
void Engine::DidNavigateLocally(const mojo::String& url) {
|
||||
|
@ -69,7 +69,11 @@ class Engine : public UIDelegate,
|
||||
void OnViewportMetricsChanged(int width, int height,
|
||||
float device_pixel_ratio) override;
|
||||
void OnInputEvent(InputEventPtr event) override;
|
||||
void LoadURL(const mojo::String& url) override;
|
||||
|
||||
void RunFromNetwork(const mojo::String& url) override;
|
||||
void RunFromFile(const mojo::String& main,
|
||||
const mojo::String& package_root) override;
|
||||
void RunFromSnapshot(mojo::ScopedDataPipeConsumerHandle snapshot) override;
|
||||
|
||||
// WebViewClient methods:
|
||||
void frameDetached(blink::WebFrame*) override;
|
||||
@ -95,12 +99,17 @@ class Engine : public UIDelegate,
|
||||
void DidNavigateLocally(const mojo::String& url) override;
|
||||
void RequestNavigateHistory(int32_t delta) override;
|
||||
|
||||
void RunFromLibrary(const mojo::String& name);
|
||||
void CloseWebViewIfNeeded();
|
||||
void LoadUsingWebView(const mojo::String& mojo_url);
|
||||
|
||||
void UpdateSkyViewSize();
|
||||
void UpdateWebViewSize();
|
||||
|
||||
Config config_;
|
||||
scoped_ptr<Animator> animator_;
|
||||
|
||||
scoped_ptr<blink::DartLibraryProvider> dart_library_provider_;
|
||||
std::unique_ptr<blink::SkyView> sky_view_;
|
||||
blink::WebView* web_view_;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user