OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 return m_loader->importedDocument(); | 63 return m_loader->importedDocument(); |
64 } | 64 } |
65 | 65 |
66 void LinkImport::process() | 66 void LinkImport::process() |
67 { | 67 { |
68 if (m_loader) | 68 if (m_loader) |
69 return; | 69 return; |
70 if (!m_owner) | 70 if (!m_owner) |
71 return; | 71 return; |
72 | 72 |
73 if (!m_owner->document()->frame() && !m_owner->document()->imports()) | 73 if (!m_owner->document()->frame() && !m_owner->document()->import()) |
74 return; | 74 return; |
75 | 75 |
76 LinkRequestBuilder builder(m_owner); | 76 LinkRequestBuilder builder(m_owner); |
77 if (!builder.isValid()) | 77 if (!builder.isValid()) |
78 return; | 78 return; |
79 | 79 |
80 HTMLImportsController* controller = m_owner->document()->imports(); | 80 if (!m_owner->document()->import()) { |
81 if (!controller) { | |
82 ASSERT(m_owner->document()->frame()); // The document should be the mast
er. | 81 ASSERT(m_owner->document()->frame()); // The document should be the mast
er. |
83 m_owner->document()->setImports(HTMLImportsController::create(m_owner->d
ocument())); | 82 HTMLImportsController::provideTo(m_owner->document()); |
84 controller = m_owner->document()->imports(); | |
85 } | 83 } |
86 | 84 |
| 85 HTMLImportsController* controller = m_owner->document()->import()->controlle
r(); |
87 if (RefPtr<HTMLImportLoader> found = controller->findLinkFor(builder.url()))
{ | 86 if (RefPtr<HTMLImportLoader> found = controller->findLinkFor(builder.url()))
{ |
88 m_loader = found; | 87 m_loader = found; |
89 return; | 88 return; |
90 } | 89 } |
91 | 90 |
92 CachedResourceRequest request = builder.build(true); | 91 CachedResourceRequest request = builder.build(true); |
93 request.setPotentiallyCrossOriginEnabled(controller->securityOrigin(), DoNot
AllowStoredCredentials); | 92 request.setPotentiallyCrossOriginEnabled(controller->securityOrigin(), DoNot
AllowStoredCredentials); |
94 CachedResourceHandle<CachedRawResource> resource = controller->cachedResourc
eLoader()->requestRawResource(request); | 93 CachedResourceHandle<CachedRawResource> resource = controller->cachedResourc
eLoader()->requestRawResource(request); |
95 if (!resource) | 94 if (!resource) |
96 return; | 95 return; |
97 | 96 |
98 m_loader = HTMLImportLoader::create(controller, builder.url(), resource); | 97 m_loader = HTMLImportLoader::create(controller, builder.url(), resource); |
99 } | 98 } |
100 | 99 |
101 void LinkImport::ownerRemoved() | 100 void LinkImport::ownerRemoved() |
102 { | 101 { |
103 m_owner = 0; | 102 m_owner = 0; |
104 m_loader.clear(); | 103 m_loader.clear(); |
105 } | 104 } |
106 | 105 |
107 | 106 |
108 PassRefPtr<HTMLImportLoader> HTMLImportLoader::create(HTMLImportsController* con
troller, const KURL& url, const CachedResourceHandle<CachedScript>& resource) | 107 PassRefPtr<HTMLImportLoader> HTMLImportLoader::create(HTMLImport* parent, const
KURL& url, const CachedResourceHandle<CachedScript>& resource) |
109 { | 108 { |
110 RefPtr<HTMLImportLoader> loader = adoptRef(new HTMLImportLoader(controller,
url, resource)); | 109 RefPtr<HTMLImportLoader> loader = adoptRef(new HTMLImportLoader(parent, url,
resource)); |
111 controller->addImport(loader); | 110 loader->controller()->addImport(loader); |
112 return loader; | 111 return loader.release(); |
113 } | 112 } |
114 | 113 |
115 HTMLImportLoader::HTMLImportLoader(HTMLImportsController* controller, const KURL
& url, const CachedResourceHandle<CachedScript>& resource) | 114 HTMLImportLoader::HTMLImportLoader(HTMLImport* parent, const KURL& url, const Ca
chedResourceHandle<CachedScript>& resource) |
116 : m_controller(controller) | 115 : m_parent(parent) |
117 , m_state(StateLoading) | 116 , m_state(StateLoading) |
118 , m_resource(resource) | 117 , m_resource(resource) |
119 , m_url(url) | 118 , m_url(url) |
120 { | 119 { |
121 m_resource->addClient(this); | 120 m_resource->addClient(this); |
122 } | 121 } |
123 | 122 |
124 HTMLImportLoader::~HTMLImportLoader() | 123 HTMLImportLoader::~HTMLImportLoader() |
125 { | 124 { |
| 125 // importDestroyed() should be called before the destruction. |
| 126 ASSERT(!m_parent); |
| 127 ASSERT(!m_importedDocument); |
126 if (m_resource) | 128 if (m_resource) |
127 m_resource->removeClient(this); | 129 m_resource->removeClient(this); |
128 } | 130 } |
129 | 131 |
130 void HTMLImportLoader::responseReceived(CachedResource*, const ResourceResponse&
response) | 132 void HTMLImportLoader::responseReceived(CachedResource*, const ResourceResponse&
response) |
131 { | 133 { |
132 setState(startParsing(response)); | 134 setState(startParsing(response)); |
133 } | 135 } |
134 | 136 |
135 void HTMLImportLoader::dataReceived(CachedResource*, const char* data, int lengt
h) | 137 void HTMLImportLoader::dataReceived(CachedResource*, const char* data, int lengt
h) |
(...skipping 24 matching lines...) Expand all Loading... |
160 m_writer->end(); | 162 m_writer->end(); |
161 m_writer.clear(); | 163 m_writer.clear(); |
162 } | 164 } |
163 | 165 |
164 if (m_resource) { | 166 if (m_resource) { |
165 m_resource->removeClient(this); | 167 m_resource->removeClient(this); |
166 m_resource = 0; | 168 m_resource = 0; |
167 } | 169 } |
168 | 170 |
169 | 171 |
170 if (m_controller) | 172 if (HTMLImportsController* controller = this->controller()) |
171 m_controller->didLoad(); | 173 controller->didLoad(this); |
172 } | 174 } |
173 | 175 |
174 HTMLImportLoader::State HTMLImportLoader::startParsing(const ResourceResponse& r
esponse) | 176 HTMLImportLoader::State HTMLImportLoader::startParsing(const ResourceResponse& r
esponse) |
175 { | 177 { |
176 // Current canAccess() implementation isn't sufficient for catching cross-do
main redirects: http://crbug.com/256976 | 178 // Current canAccess() implementation isn't sufficient for catching cross-do
main redirects: http://crbug.com/256976 |
177 if (!m_controller->cachedResourceLoader()->canAccess(m_resource.get())) | 179 if (!controller()->cachedResourceLoader()->canAccess(m_resource.get())) |
178 return StateError; | 180 return StateError; |
179 | 181 |
180 m_importedDocument = HTMLDocument::create(0, response.url()); | 182 m_importedDocument = HTMLDocument::create(0, response.url()); |
181 m_importedDocument->setImports(m_controller); | 183 m_importedDocument->setImport(this); |
182 m_writer = DocumentWriter::create(m_importedDocument.get(), response.mimeTyp
e(), response.textEncodingName()); | 184 m_writer = DocumentWriter::create(m_importedDocument.get(), response.mimeTyp
e(), response.textEncodingName()); |
183 | 185 |
184 return StateLoading; | 186 return StateLoading; |
185 } | 187 } |
186 | 188 |
187 HTMLImportLoader::State HTMLImportLoader::finish() | 189 HTMLImportLoader::State HTMLImportLoader::finish() |
188 { | 190 { |
189 if (!m_controller) | 191 if (!m_parent) |
190 return StateError; | 192 return StateError; |
191 // The writer instance indicates that a part of the document can be already
loaded. | 193 // The writer instance indicates that a part of the document can be already
loaded. |
192 // We don't take such a case as an error because the partially-loaded docume
nt has been visible from script at this point. | 194 // We don't take such a case as an error because the partially-loaded docume
nt has been visible from script at this point. |
193 if (m_resource->loadFailedOrCanceled() && !m_writer) | 195 if (m_resource->loadFailedOrCanceled() && !m_writer) |
194 return StateError; | 196 return StateError; |
195 return StateReady; | 197 return StateReady; |
196 } | 198 } |
197 | 199 |
198 Document* HTMLImportLoader::importedDocument() const | 200 Document* HTMLImportLoader::importedDocument() const |
199 { | 201 { |
200 if (m_state != StateReady) | 202 if (m_state != StateReady) |
201 return 0; | 203 return 0; |
202 return m_importedDocument.get(); | 204 return m_importedDocument.get(); |
203 } | 205 } |
204 | 206 |
205 void HTMLImportLoader::importDestroyed() | 207 void HTMLImportLoader::importDestroyed() |
206 { | 208 { |
207 m_controller = 0; | 209 m_parent = 0; |
208 m_importedDocument.clear(); | 210 if (RefPtr<Document> document = m_importedDocument.release()) |
| 211 document->setImport(0); |
209 } | 212 } |
210 | 213 |
| 214 HTMLImportsController* HTMLImportLoader::controller() |
| 215 { |
| 216 return m_parent ? m_parent->controller() : 0; |
| 217 } |
211 | 218 |
212 PassRefPtr<HTMLImportsController> HTMLImportsController::create(Document* master
) | 219 HTMLImport* HTMLImportLoader::parent() |
213 { | 220 { |
214 return adoptRef(new HTMLImportsController(master)); | 221 return m_parent; |
| 222 } |
| 223 |
| 224 Document* HTMLImportLoader::document() |
| 225 { |
| 226 return m_importedDocument.get(); |
| 227 } |
| 228 |
| 229 void HTMLImportLoader::wasDetachedFromDocument() |
| 230 { |
| 231 // For imported documens this shouldn't be called because Document::m_import
is |
| 232 // cleared before Document is destroyed by HTMLImportLoader::importDestroyed
(). |
| 233 ASSERT_NOT_REACHED(); |
| 234 } |
| 235 |
| 236 void HTMLImportsController::provideTo(Document* master) |
| 237 { |
| 238 DEFINE_STATIC_LOCAL(const char*, name, ("HTMLImportsController")); |
| 239 OwnPtr<HTMLImportsController> controller = adoptPtr(new HTMLImportsControlle
r(master)); |
| 240 master->setImport(controller.get()); |
| 241 Supplement<ScriptExecutionContext>::provideTo(master, name, controller.relea
se()); |
215 } | 242 } |
216 | 243 |
217 HTMLImportsController::HTMLImportsController(Document* master) | 244 HTMLImportsController::HTMLImportsController(Document* master) |
218 : m_master(master) | 245 : m_master(master) |
219 { | 246 { |
220 } | 247 } |
221 | 248 |
222 HTMLImportsController::~HTMLImportsController() | 249 HTMLImportsController::~HTMLImportsController() |
223 { | 250 { |
| 251 ASSERT(!m_master); |
| 252 } |
| 253 |
| 254 void HTMLImportsController::clear() |
| 255 { |
224 for (size_t i = 0; i < m_imports.size(); ++i) | 256 for (size_t i = 0; i < m_imports.size(); ++i) |
225 m_imports[i]->importDestroyed(); | 257 m_imports[i]->importDestroyed(); |
| 258 if (m_master) |
| 259 m_master->setImport(0); |
| 260 m_master = 0; |
226 } | 261 } |
227 | 262 |
228 void HTMLImportsController::addImport(PassRefPtr<HTMLImportLoader> link) | 263 void HTMLImportsController::addImport(PassRefPtr<HTMLImportLoader> link) |
229 { | 264 { |
230 ASSERT(!link->url().isEmpty() && link->url().isValid()); | 265 ASSERT(!link->url().isEmpty() && link->url().isValid()); |
231 m_imports.append(link); | 266 m_imports.append(link); |
232 } | 267 } |
233 | 268 |
234 void HTMLImportsController::showSecurityErrorMessage(const String& message) | 269 void HTMLImportsController::showSecurityErrorMessage(const String& message) |
235 { | 270 { |
236 m_master->addConsoleMessage(JSMessageSource, ErrorMessageLevel, message); | 271 m_master->addConsoleMessage(JSMessageSource, ErrorMessageLevel, message); |
237 } | 272 } |
238 | 273 |
239 void HTMLImportsController::didLoad() | 274 void HTMLImportsController::didLoad(HTMLImportLoader* loadedImport) |
240 { | 275 { |
241 if (haveLoaded()) | 276 for (HTMLImport* ancestorToNotify = loadedImport->parent(); ancestorToNotify
; ancestorToNotify = ancestorToNotify->parent()) { |
242 m_master->didLoadAllImports(); | 277 if (haveChildrenLoaded(ancestorToNotify)) |
| 278 ancestorToNotify->document()->didLoadAllImports(); |
| 279 } |
243 } | 280 } |
244 | 281 |
245 PassRefPtr<HTMLImportLoader> HTMLImportsController::findLinkFor(const KURL& url)
const | 282 PassRefPtr<HTMLImportLoader> HTMLImportsController::findLinkFor(const KURL& url)
const |
246 { | 283 { |
247 for (size_t i = 0; i < m_imports.size(); ++i) { | 284 for (size_t i = 0; i < m_imports.size(); ++i) { |
248 if (equalIgnoringFragmentIdentifier(m_imports[i]->url(), url)) | 285 if (equalIgnoringFragmentIdentifier(m_imports[i]->url(), url)) |
249 return m_imports[i]; | 286 return m_imports[i]; |
250 } | 287 } |
251 | 288 |
252 return 0; | 289 return 0; |
253 } | 290 } |
254 | 291 |
255 SecurityOrigin* HTMLImportsController::securityOrigin() const | 292 SecurityOrigin* HTMLImportsController::securityOrigin() const |
256 { | 293 { |
257 return m_master->securityOrigin(); | 294 return m_master->securityOrigin(); |
258 } | 295 } |
259 | 296 |
260 CachedResourceLoader* HTMLImportsController::cachedResourceLoader() const | 297 CachedResourceLoader* HTMLImportsController::cachedResourceLoader() const |
261 { | 298 { |
262 return m_master->cachedResourceLoader(); | 299 return m_master->cachedResourceLoader(); |
263 } | 300 } |
264 | 301 |
265 bool HTMLImportsController::haveLoaded() const | 302 bool HTMLImportsController::haveChildrenLoaded(HTMLImport* parent) const |
266 { | 303 { |
267 for (size_t i = 0; i < m_imports.size(); ++i) { | 304 for (size_t i = 0; i < m_imports.size(); ++i) { |
268 if (!m_imports[i]->isDone()) | 305 if (!m_imports[i]->isDone() && m_imports[i]->parent() == parent) |
269 return false; | 306 return false; |
270 } | 307 } |
271 | 308 |
272 return true; | 309 return true; |
273 } | 310 } |
274 | 311 |
| 312 HTMLImportsController* HTMLImportsController::controller() |
| 313 { |
| 314 return this; |
| 315 } |
| 316 |
| 317 HTMLImport* HTMLImportsController::parent() |
| 318 { |
| 319 return 0; |
| 320 } |
| 321 |
| 322 Document* HTMLImportsController::document() |
| 323 { |
| 324 return m_master; |
| 325 } |
| 326 |
| 327 void HTMLImportsController::wasDetachedFromDocument() |
| 328 { |
| 329 clear(); |
| 330 } |
| 331 |
275 } // namespace WebCore | 332 } // namespace WebCore |
OLD | NEW |