Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: sky/engine/tonic/dart_library_loader.cc

Issue 1202283004: Factor DartLibraryProvider out of DartLoader (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sky/engine/tonic/dart_library_loader.h ('k') | sky/engine/tonic/dart_library_provider.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "sky/engine/core/script/dart_loader.h" 5 #include "sky/engine/tonic/dart_library_loader.h"
6 6
7 #include "base/callback.h" 7 #include "base/callback.h"
8 #include "base/trace_event/trace_event.h" 8 #include "base/trace_event/trace_event.h"
9 #include "mojo/common/data_pipe_drainer.h" 9 #include "mojo/common/data_pipe_drainer.h"
10 #include "sky/engine/core/script/dart_dependency_catcher.h"
11 #include "sky/engine/core/script/dom_dart_state.h"
12 #include "sky/engine/platform/fetcher/MojoFetcher.h"
13 #include "sky/engine/platform/weborigin/KURL.h"
14 #include "sky/engine/tonic/dart_api_scope.h" 10 #include "sky/engine/tonic/dart_api_scope.h"
15 #include "sky/engine/tonic/dart_converter.h" 11 #include "sky/engine/tonic/dart_converter.h"
12 #include "sky/engine/tonic/dart_dependency_catcher.h"
16 #include "sky/engine/tonic/dart_error.h" 13 #include "sky/engine/tonic/dart_error.h"
17 #include "sky/engine/tonic/dart_isolate_scope.h" 14 #include "sky/engine/tonic/dart_isolate_scope.h"
15 #include "sky/engine/tonic/dart_library_provider.h"
16 #include "sky/engine/tonic/dart_state.h"
18 #include "sky/engine/wtf/MainThread.h" 17 #include "sky/engine/wtf/MainThread.h"
19 18
20 using mojo::common::DataPipeDrainer; 19 using mojo::common::DataPipeDrainer;
21 20
22 namespace blink { 21 namespace blink {
23 namespace {
24 22
25 Dart_Handle CanonicalizeURL(DartState* state, 23 // A DartLibraryLoader::Job represents a network load. It fetches data from the
26 Dart_Handle library, 24 // network and buffers the data in Vector. To cancel the job, delete this
27 Dart_Handle url) { 25 // object.
28 String string = StringFromDart(url); 26 class DartLibraryLoader::Job : public DartDependency,
29 if (string.startsWith("dart:")) 27 public DataPipeDrainer::Client {
30 return url;
31 // TODO(dart): Figure out how 'package:' should work in sky.
32 if (string.startsWith("package:")) {
33 string.replace("package:", "/packages/");
34 }
35 String library_url_string = StringFromDart(Dart_LibraryUrl(library));
36 KURL library_url = KURL(ParsedURLString, library_url_string);
37 KURL resolved_url = KURL(library_url, string);
38 return StringToDart(state, resolved_url.string());
39 }
40
41 } // namespace
42
43 // A DartLoader::Job represents a network load. It fetches data from the network
44 // and buffers the data in Vector. To cancel the job, delete this object.
45 class DartLoader::Job : public DartDependency,
46 public MojoFetcher::Client,
47 public DataPipeDrainer::Client {
48 public: 28 public:
49 Job(DartLoader* loader, const KURL& url, mojo::URLResponsePtr response) 29 Job(DartLibraryLoader* loader, const String& name)
50 : loader_(loader), url_(url) 30 : loader_(loader), name_(name), weak_factory_(this) {
51 { 31 loader->library_provider()->GetLibraryAsStream(
52 if (!response) { 32 name, base::Bind(&Job::OnStreamAvailable, weak_factory_.GetWeakPtr()));
53 fetcher_ = adoptPtr(new MojoFetcher(this, url));
54 } else {
55 OnReceivedResponse(response.Pass());
56 }
57 } 33 }
58 34
59 const KURL& url() const { return url_; } 35 const String& name() const { return name_; }
60 36
61 protected: 37 protected:
62 DartLoader* loader_; 38 DartLibraryLoader* loader_;
63 // TODO(abarth): Should we be using SharedBuffer to buffer the data? 39 // TODO(abarth): Should we be using SharedBuffer to buffer the data?
64 Vector<uint8_t> buffer_; 40 Vector<uint8_t> buffer_;
65 41
66 private: 42 private:
67 // MojoFetcher::Client 43 void OnStreamAvailable(mojo::ScopedDataPipeConsumerHandle pipe) {
68 void OnReceivedResponse(mojo::URLResponsePtr response) override { 44 if (!pipe.is_valid()) {
69 if (response->status_code != 200) {
70 loader_->DidFailJob(this); 45 loader_->DidFailJob(this);
71 return; 46 return;
72 } 47 }
73 drainer_ = adoptPtr(new DataPipeDrainer(this, response->body.Pass())); 48 drainer_ = adoptPtr(new DataPipeDrainer(this, pipe.Pass()));
74 } 49 }
75 50
76 // DataPipeDrainer::Client 51 // DataPipeDrainer::Client
77 void OnDataAvailable(const void* data, size_t num_bytes) override { 52 void OnDataAvailable(const void* data, size_t num_bytes) override {
78 buffer_.append(static_cast<const uint8_t*>(data), num_bytes); 53 buffer_.append(static_cast<const uint8_t*>(data), num_bytes);
79 } 54 }
80 // Subclasses must implement OnDataComplete. 55 // Subclasses must implement OnDataComplete.
81 56
82 KURL url_; 57 String name_;
83 OwnPtr<MojoFetcher> fetcher_;
84 OwnPtr<DataPipeDrainer> drainer_; 58 OwnPtr<DataPipeDrainer> drainer_;
59
60 base::WeakPtrFactory<Job> weak_factory_;
85 }; 61 };
86 62
87 class DartLoader::ImportJob : public Job { 63 class DartLibraryLoader::ImportJob : public Job {
88 public: 64 public:
89 ImportJob(DartLoader* loader, const KURL& url, mojo::URLResponsePtr response = nullptr) 65 ImportJob(DartLibraryLoader* loader, const String& name) : Job(loader, name) {
90 : Job(loader, url, response.Pass()) { 66 TRACE_EVENT_ASYNC_BEGIN1("sky", "DartLibraryLoader::ImportJob", this, "url",
91 TRACE_EVENT_ASYNC_BEGIN1("sky", "DartLoader::ImportJob", this, 67 name.ascii().toStdString());
92 "url", url.string().ascii().toStdString());
93 } 68 }
94 69
95 private: 70 private:
96 // DataPipeDrainer::Client 71 // DataPipeDrainer::Client
97 void OnDataComplete() override { 72 void OnDataComplete() override {
98 TRACE_EVENT_ASYNC_END0("sky", "DartLoader::ImportJob", this); 73 TRACE_EVENT_ASYNC_END0("sky", "DartLibraryLoader::ImportJob", this);
99 loader_->DidCompleteImportJob(this, buffer_); 74 loader_->DidCompleteImportJob(this, buffer_);
100 } 75 }
101 }; 76 };
102 77
103 class DartLoader::SourceJob : public Job { 78 class DartLibraryLoader::SourceJob : public Job {
104 public: 79 public:
105 SourceJob(DartLoader* loader, const KURL& url, Dart_Handle library) 80 SourceJob(DartLibraryLoader* loader, const String& name, Dart_Handle library)
106 : Job(loader, url, nullptr), library_(loader->dart_state(), library) { 81 : Job(loader, name), library_(loader->dart_state(), library) {
107 TRACE_EVENT_ASYNC_BEGIN1("sky", "DartLoader::SourceJob", this, 82 TRACE_EVENT_ASYNC_BEGIN1("sky", "DartLibraryLoader::SourceJob", this, "url",
108 "url", url.string().ascii().toStdString()); 83 name.ascii().toStdString());
109 } 84 }
110 85
111 Dart_PersistentHandle library() const { return library_.value(); } 86 Dart_PersistentHandle library() const { return library_.value(); }
112 87
113 private: 88 private:
114 // DataPipeDrainer::Client 89 // DataPipeDrainer::Client
115 void OnDataComplete() override { 90 void OnDataComplete() override {
116 TRACE_EVENT_ASYNC_END0("sky", "DartLoader::SourceJob", this); 91 TRACE_EVENT_ASYNC_END0("sky", "DartLibraryLoader::SourceJob", this);
117 loader_->DidCompleteSourceJob(this, buffer_); 92 loader_->DidCompleteSourceJob(this, buffer_);
118 } 93 }
119 94
120 DartPersistentValue library_; 95 DartPersistentValue library_;
121 }; 96 };
122 97
123 // A DependencyWatcher represents a request to watch for when a given set of 98 // A DependencyWatcher represents a request to watch for when a given set of
124 // dependencies (either libraries or parts of libraries) have finished loading. 99 // dependencies (either libraries or parts of libraries) have finished loading.
125 // When the dependencies are satisfied (including transitive dependencies), then 100 // When the dependencies are satisfied (including transitive dependencies), then
126 // the |callback| will be invoked. 101 // the |callback| will be invoked.
127 class DartLoader::DependencyWatcher { 102 class DartLibraryLoader::DependencyWatcher {
128 public: 103 public:
129 DependencyWatcher(const HashSet<DartDependency*>& dependencies, 104 DependencyWatcher(const HashSet<DartDependency*>& dependencies,
130 const base::Closure& callback) 105 const base::Closure& callback)
131 : dependencies_(dependencies), callback_(callback) { 106 : dependencies_(dependencies), callback_(callback) {
132 DCHECK(!dependencies_.isEmpty()); 107 DCHECK(!dependencies_.isEmpty());
133 } 108 }
134 109
135 bool DidResolveDependency(DartDependency* resolved_dependency, 110 bool DidResolveDependency(DartDependency* resolved_dependency,
136 const HashSet<DartDependency*>& new_dependencies) { 111 const HashSet<DartDependency*>& new_dependencies) {
137 const auto& it = dependencies_.find(resolved_dependency); 112 const auto& it = dependencies_.find(resolved_dependency);
(...skipping 12 matching lines...) Expand all
150 base::Closure callback_; 125 base::Closure callback_;
151 }; 126 };
152 127
153 // A WatcherSignaler is responsible for signaling DependencyWatchers when their 128 // A WatcherSignaler is responsible for signaling DependencyWatchers when their
154 // dependencies resolve and for calling the DependencyWatcher's callback. We use 129 // dependencies resolve and for calling the DependencyWatcher's callback. We use
155 // a separate object of this task because we want to carefully manage when we 130 // a separate object of this task because we want to carefully manage when we
156 // call the callbacks, which can call into us again reentrantly. 131 // call the callbacks, which can call into us again reentrantly.
157 // 132 //
158 // WatcherSignaler is designed to be placed on the stack as a RAII. After its 133 // WatcherSignaler is designed to be placed on the stack as a RAII. After its
159 // destructor runs, we might have executed aribitrary script. 134 // destructor runs, we might have executed aribitrary script.
160 class DartLoader::WatcherSignaler { 135 class DartLibraryLoader::WatcherSignaler {
161 public: 136 public:
162 WatcherSignaler(DartLoader& loader, DartDependency* resolved_dependency) 137 WatcherSignaler(DartLibraryLoader& loader,
138 DartDependency* resolved_dependency)
163 : loader_(loader), 139 : loader_(loader),
164 catcher_(adoptPtr(new DartDependencyCatcher(loader))), 140 catcher_(adoptPtr(new DartDependencyCatcher(loader))),
165 resolved_dependency_(resolved_dependency) {} 141 resolved_dependency_(resolved_dependency) {}
166 142
167 ~WatcherSignaler() { 143 ~WatcherSignaler() {
168 Vector<DependencyWatcher*> completed_watchers; 144 Vector<DependencyWatcher*> completed_watchers;
169 for (const auto& watcher : loader_.dependency_watchers_) { 145 for (const auto& watcher : loader_.dependency_watchers_) {
170 if (watcher->DidResolveDependency(resolved_dependency_, 146 if (watcher->DidResolveDependency(resolved_dependency_,
171 catcher_->dependencies())) 147 catcher_->dependencies()))
172 completed_watchers.append(watcher.get()); 148 completed_watchers.append(watcher.get());
173 } 149 }
174 150
175 // Notice that we remove the dependency catcher and extract all the 151 // Notice that we remove the dependency catcher and extract all the
176 // callbacks before running any of them. We don't want to be re-entered 152 // callbacks before running any of them. We don't want to be re-entered
177 // below the callbacks and end up in an inconsistent state. 153 // below the callbacks and end up in an inconsistent state.
178 catcher_.clear(); 154 catcher_.clear();
179 Vector<base::Closure> callbacks; 155 Vector<base::Closure> callbacks;
180 for (const auto& watcher : completed_watchers) { 156 for (const auto& watcher : completed_watchers) {
181 callbacks.append(watcher->callback()); 157 callbacks.append(watcher->callback());
182 loader_.dependency_watchers_.remove(watcher); 158 loader_.dependency_watchers_.remove(watcher);
183 } 159 }
184 160
185 // Finally, run all the callbacks while touching only data on the stack. 161 // Finally, run all the callbacks while touching only data on the stack.
186 for (const auto& callback : callbacks) 162 for (const auto& callback : callbacks)
187 callback.Run(); 163 callback.Run();
188 } 164 }
189 165
190 private: 166 private:
191 DartLoader& loader_; 167 DartLibraryLoader& loader_;
192 OwnPtr<DartDependencyCatcher> catcher_; 168 OwnPtr<DartDependencyCatcher> catcher_;
193 DartDependency* resolved_dependency_; 169 DartDependency* resolved_dependency_;
194 }; 170 };
195 171
196 DartLoader::DartLoader(DartState* dart_state) 172 DartLibraryLoader::DartLibraryLoader(DartState* dart_state)
197 : dart_state_(dart_state->GetWeakPtr()), 173 : dart_state_(dart_state),
174 library_provider_(nullptr),
198 dependency_catcher_(nullptr) { 175 dependency_catcher_(nullptr) {
199 } 176 }
200 177
201 DartLoader::~DartLoader() { 178 DartLibraryLoader::~DartLibraryLoader() {
202 } 179 }
203 180
204 Dart_Handle DartLoader::HandleLibraryTag(Dart_LibraryTag tag, 181 Dart_Handle DartLibraryLoader::HandleLibraryTag(Dart_LibraryTag tag,
205 Dart_Handle library, 182 Dart_Handle library,
206 Dart_Handle url) { 183 Dart_Handle url) {
207 DCHECK(Dart_IsLibrary(library)); 184 DCHECK(Dart_IsLibrary(library));
208 DCHECK(Dart_IsString(url)); 185 DCHECK(Dart_IsString(url));
209 if (tag == Dart_kCanonicalizeUrl) 186 if (tag == Dart_kCanonicalizeUrl)
210 return CanonicalizeURL(DartState::Current(), library, url); 187 return DartState::Current()->library_loader().CanonicalizeURL(library, url);
211 if (tag == Dart_kImportTag) { 188 if (tag == Dart_kImportTag) {
212 CHECK(WTF::isMainThread()); 189 CHECK(WTF::isMainThread());
213 return DOMDartState::Current()->loader().Import(library, url); 190 return DartState::Current()->library_loader().Import(library, url);
214 } 191 }
215 if (tag == Dart_kSourceTag) { 192 if (tag == Dart_kSourceTag) {
216 CHECK(WTF::isMainThread()); 193 CHECK(WTF::isMainThread());
217 return DOMDartState::Current()->loader().Source(library, url); 194 return DartState::Current()->library_loader().Source(library, url);
218 } 195 }
219 DCHECK(false); 196 DCHECK(false);
220 return Dart_NewApiError("Unknown library tag."); 197 return Dart_NewApiError("Unknown library tag.");
221 } 198 }
222 199
223 void DartLoader::WaitForDependencies( 200 void DartLibraryLoader::WaitForDependencies(
224 const HashSet<DartDependency*>& dependencies, 201 const HashSet<DartDependency*>& dependencies,
225 const base::Closure& callback) { 202 const base::Closure& callback) {
226 if (dependencies.isEmpty()) 203 if (dependencies.isEmpty())
227 return callback.Run(); 204 return callback.Run();
228 dependency_watchers_.add( 205 dependency_watchers_.add(
229 adoptPtr(new DependencyWatcher(dependencies, callback))); 206 adoptPtr(new DependencyWatcher(dependencies, callback)));
230 } 207 }
231 208
232 void DartLoader::LoadLibrary(const KURL& url, mojo::URLResponsePtr response) { 209 void DartLibraryLoader::LoadLibrary(const String& name) {
233 if (response && response->status_code >= 400) { 210 const auto& result = pending_libraries_.add(name, nullptr);
234 LOG(ERROR) << url.string().utf8().data()
235 << " failed with " << response->status_code;
236 }
237
238 const auto& result = pending_libraries_.add(url.string(), nullptr);
239 if (result.isNewEntry) { 211 if (result.isNewEntry) {
240 OwnPtr<Job> job = adoptPtr(new ImportJob(this, url)); 212 OwnPtr<Job> job = adoptPtr(new ImportJob(this, name));
241 result.storedValue->value = job.get(); 213 result.storedValue->value = job.get();
242 jobs_.add(job.release()); 214 jobs_.add(job.release());
243 } 215 }
244 if (dependency_catcher_) 216 if (dependency_catcher_)
245 dependency_catcher_->AddDependency(result.storedValue->value); 217 dependency_catcher_->AddDependency(result.storedValue->value);
246 } 218 }
247 219
248 Dart_Handle DartLoader::Import(Dart_Handle library, Dart_Handle url) { 220 Dart_Handle DartLibraryLoader::Import(Dart_Handle library, Dart_Handle url) {
249 LoadLibrary(KURL(ParsedURLString, StringFromDart(url))); 221 LoadLibrary(StringFromDart(url));
250 return Dart_True(); 222 return Dart_True();
251 } 223 }
252 224
253 Dart_Handle DartLoader::Source(Dart_Handle library, Dart_Handle url) { 225 Dart_Handle DartLibraryLoader::Source(Dart_Handle library, Dart_Handle url) {
254 KURL parsed_url(ParsedURLString, StringFromDart(url)); 226 OwnPtr<Job> job = adoptPtr(new SourceJob(this, StringFromDart(url), library));
255 OwnPtr<Job> job = adoptPtr(new SourceJob(this, parsed_url, library));
256 if (dependency_catcher_) 227 if (dependency_catcher_)
257 dependency_catcher_->AddDependency(job.get()); 228 dependency_catcher_->AddDependency(job.get());
258 jobs_.add(job.release()); 229 jobs_.add(job.release());
259 return Dart_True(); 230 return Dart_True();
260 } 231 }
261 232
262 void DartLoader::DidCompleteImportJob(ImportJob* job, 233 Dart_Handle DartLibraryLoader::CanonicalizeURL(Dart_Handle library,
263 const Vector<uint8_t>& buffer) { 234 Dart_Handle url) {
264 DCHECK(dart_state_); 235 return library_provider_->CanonicalizeURL(library, url);
236 }
237
238 void DartLibraryLoader::DidCompleteImportJob(ImportJob* job,
239 const Vector<uint8_t>& buffer) {
265 DartIsolateScope scope(dart_state_->isolate()); 240 DartIsolateScope scope(dart_state_->isolate());
266 DartApiScope api_scope; 241 DartApiScope api_scope;
267 242
268 WatcherSignaler watcher_signaler(*this, job); 243 WatcherSignaler watcher_signaler(*this, job);
269 244
270 String url_string = job->url().string();
271 LogIfError(Dart_LoadLibrary( 245 LogIfError(Dart_LoadLibrary(
272 StringToDart(dart_state_.get(), url_string), 246 StringToDart(dart_state_, job->name()),
273 Dart_NewStringFromUTF8(buffer.data(), buffer.size()), 0, 0)); 247 Dart_NewStringFromUTF8(buffer.data(), buffer.size()), 0, 0));
274 248
275 pending_libraries_.remove(url_string); 249 pending_libraries_.remove(job->name());
276 jobs_.remove(job); 250 jobs_.remove(job);
277 } 251 }
278 252
279 void DartLoader::DidCompleteSourceJob(SourceJob* job, 253 void DartLibraryLoader::DidCompleteSourceJob(SourceJob* job,
280 const Vector<uint8_t>& buffer) { 254 const Vector<uint8_t>& buffer) {
281 DCHECK(dart_state_);
282 DartIsolateScope scope(dart_state_->isolate()); 255 DartIsolateScope scope(dart_state_->isolate());
283 DartApiScope api_scope; 256 DartApiScope api_scope;
284 257
285 WatcherSignaler watcher_signaler(*this, job); 258 WatcherSignaler watcher_signaler(*this, job);
286 259
287 LogIfError(Dart_LoadSource( 260 LogIfError(Dart_LoadSource(
288 Dart_HandleFromPersistent(job->library()), 261 Dart_HandleFromPersistent(job->library()),
289 StringToDart(dart_state_.get(), job->url().string()), 262 StringToDart(dart_state_, job->name()),
290 Dart_NewStringFromUTF8(buffer.data(), buffer.size()), 0, 0)); 263 Dart_NewStringFromUTF8(buffer.data(), buffer.size()), 0, 0));
291 264
292 jobs_.remove(job); 265 jobs_.remove(job);
293 } 266 }
294 267
295 void DartLoader::DidFailJob(Job* job) { 268 void DartLibraryLoader::DidFailJob(Job* job) {
296 DCHECK(dart_state_);
297 DartIsolateScope scope(dart_state_->isolate()); 269 DartIsolateScope scope(dart_state_->isolate());
298 DartApiScope api_scope; 270 DartApiScope api_scope;
299 271
300 WatcherSignaler watcher_signaler(*this, job); 272 WatcherSignaler watcher_signaler(*this, job);
301 273
302 LOG(ERROR) << "Library Load failed: " << job->url().string().utf8().data(); 274 LOG(ERROR) << "Library Load failed: " << job->name().utf8().data();
303 // TODO(eseidel): Call Dart_LibraryHandleError in the SourceJob case? 275 // TODO(eseidel): Call Dart_LibraryHandleError in the SourceJob case?
304 276
305 jobs_.remove(job); 277 jobs_.remove(job);
306 } 278 }
307 279
308 } // namespace blink 280 } // namespace blink
OLDNEW
« no previous file with comments | « sky/engine/tonic/dart_library_loader.h ('k') | sky/engine/tonic/dart_library_provider.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698