blob: 890ca536f9c45cb382f40e526e9e97d9727f84cc [file] [log] [blame]
John McCutchan352b6f72015-07-27 15:09:07 -07001// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "tonic/dart_library_provider_network.h"
6
7#include "base/bind.h"
8#include "base/strings/string_util.h"
9#include "tonic/dart_converter.h"
10#include "url/gurl.h"
11
12namespace tonic {
13namespace {
14
15mojo::URLLoaderPtr Fetch(mojo::NetworkService* network_service,
16 const std::string& url,
17 base::Callback<void(mojo::URLResponsePtr)> callback) {
18 mojo::URLLoaderPtr loader;
19 network_service->CreateURLLoader(GetProxy(&loader));
20
21 mojo::URLRequestPtr request = mojo::URLRequest::New();
22 request->url = url;
23 request->auto_follow_redirects = true;
24 loader->Start(request.Pass(), callback);
25
26 return loader.Pass();
27}
28
29// Helper to erase a T* from a container of std::unique_ptr<T>s.
30template<typename T, typename C>
31void EraseUniquePtr(C& container, T* item) {
32 std::unique_ptr<T> key = std::unique_ptr<T>(item);
33 container.erase(key);
34 key.release();
35}
36
37} // namespace
38
39class DartLibraryProviderNetwork::Job {
40 public:
41 Job(DartLibraryProviderNetwork* provider,
42 const std::string& name,
43 DataPipeConsumerCallback callback)
44 : provider_(provider), callback_(callback), weak_factory_(this) {
45 url_loader_ =
46 Fetch(provider_->network_service(), name,
47 base::Bind(&Job::OnReceivedResponse, weak_factory_.GetWeakPtr()));
48 }
49
50 private:
51 void OnReceivedResponse(mojo::URLResponsePtr response) {
52 mojo::ScopedDataPipeConsumerHandle data;
53 if (response->status_code == 200)
54 data = response->body.Pass();
55 callback_.Run(data.Pass());
56 EraseUniquePtr(provider_->jobs_, this);
57 // We're deleted now.
58 }
59
60 DartLibraryProviderNetwork* provider_;
61 DataPipeConsumerCallback callback_;
62 mojo::URLLoaderPtr url_loader_;
63
64 base::WeakPtrFactory<Job> weak_factory_;
65};
66
67DartLibraryProviderNetwork::DartLibraryProviderNetwork(
68 mojo::NetworkService* network_service)
69 : network_service_(network_service) {
70}
71
72DartLibraryProviderNetwork::~DartLibraryProviderNetwork() {
73}
74
75void DartLibraryProviderNetwork::GetLibraryAsStream(
76 const std::string& name,
77 DataPipeConsumerCallback callback) {
78 jobs_.insert(std::unique_ptr<Job>(new Job(this, name, callback)));
79}
80
81Dart_Handle DartLibraryProviderNetwork::CanonicalizeURL(Dart_Handle library,
82 Dart_Handle url) {
83 std::string string = StdStringFromDart(url);
84 if (StartsWithASCII(string, "dart:", true))
85 return url;
86 // TODO(abarth): The package root should be configurable.
87 if (StartsWithASCII(string, "package:", true))
88 ReplaceFirstSubstringAfterOffset(&string, 0, "package:", "/packages/");
89 GURL library_url(StdStringFromDart(Dart_LibraryUrl(library)));
90 GURL resolved_url = library_url.Resolve(string);
91 return StdStringToDart(resolved_url.spec());
92}
93
94} // namespace tonic