OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. |
3 * Copyright (C) 2013, Intel Corporation | 3 * Copyright (C) 2013, Intel Corporation |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
7 * met: | 7 * met: |
8 * | 8 * |
9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 , m_redirectMode(WebURLRequest::FetchRedirectModeFollow) | 134 , m_redirectMode(WebURLRequest::FetchRedirectModeFollow) |
135 { | 135 { |
136 ASSERT(client); | 136 ASSERT(client); |
137 } | 137 } |
138 | 138 |
139 void DocumentThreadableLoader::start(const ResourceRequest& request) | 139 void DocumentThreadableLoader::start(const ResourceRequest& request) |
140 { | 140 { |
141 // Setting an outgoing referer is only supported in the async code path. | 141 // Setting an outgoing referer is only supported in the async code path. |
142 ASSERT(m_async || request.httpReferrer().isEmpty()); | 142 ASSERT(m_async || request.httpReferrer().isEmpty()); |
143 | 143 |
144 m_sameOriginRequest = securityOrigin()->canRequestNoSuborigin(request.url())
; | 144 m_sameOriginRequest = getSecurityOrigin()->canRequestNoSuborigin(request.url
()); |
145 m_requestContext = request.requestContext(); | 145 m_requestContext = request.requestContext(); |
146 m_redirectMode = request.fetchRedirectMode(); | 146 m_redirectMode = request.fetchRedirectMode(); |
147 | 147 |
148 if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == DenyCrossO
riginRequests) { | 148 if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == DenyCrossO
riginRequests) { |
149 ThreadableLoaderClient* client = m_client; | 149 ThreadableLoaderClient* client = m_client; |
150 clear(); | 150 clear(); |
151 client->didFail(ResourceError(errorDomainBlinkInternal, 0, request.url()
.getString(), "Cross origin requests are not supported.")); | 151 client->didFail(ResourceError(errorDomainBlinkInternal, 0, request.url()
.getString(), "Cross origin requests are not supported.")); |
152 // |this| may be dead here. | 152 // |this| may be dead here. |
153 return; | 153 return; |
154 } | 154 } |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 return; | 265 return; |
266 } | 266 } |
267 | 267 |
268 // We use isSimpleOrForbiddenRequest() here since |request| may have been | 268 // We use isSimpleOrForbiddenRequest() here since |request| may have been |
269 // modified in the process of loading (not from the user's input). For | 269 // modified in the process of loading (not from the user's input). For |
270 // example, referrer. We need to accept them. For security, we must reject | 270 // example, referrer. We need to accept them. For security, we must reject |
271 // forbidden headers/methods at the point we accept user's input. Not here. | 271 // forbidden headers/methods at the point we accept user's input. Not here. |
272 if ((m_options.preflightPolicy == ConsiderPreflight && FetchUtils::isSimpleO
rForbiddenRequest(request.httpMethod(), request.httpHeaderFields())) || m_option
s.preflightPolicy == PreventPreflight) { | 272 if ((m_options.preflightPolicy == ConsiderPreflight && FetchUtils::isSimpleO
rForbiddenRequest(request.httpMethod(), request.httpHeaderFields())) || m_option
s.preflightPolicy == PreventPreflight) { |
273 ResourceRequest crossOriginRequest(request); | 273 ResourceRequest crossOriginRequest(request); |
274 ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); | 274 ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); |
275 updateRequestForAccessControl(crossOriginRequest, securityOrigin(), effe
ctiveAllowCredentials()); | 275 updateRequestForAccessControl(crossOriginRequest, getSecurityOrigin(), e
ffectiveAllowCredentials()); |
276 // We update the credentials mode according to effectiveAllowCredentials
() here for backward compatibility. But this is not correct. | 276 // We update the credentials mode according to effectiveAllowCredentials
() here for backward compatibility. But this is not correct. |
277 // FIXME: We should set it in the caller of DocumentThreadableLoader. | 277 // FIXME: We should set it in the caller of DocumentThreadableLoader. |
278 crossOriginRequest.setFetchCredentialsMode(effectiveAllowCredentials() =
= AllowStoredCredentials ? WebURLRequest::FetchCredentialsModeInclude : WebURLRe
quest::FetchCredentialsModeOmit); | 278 crossOriginRequest.setFetchCredentialsMode(effectiveAllowCredentials() =
= AllowStoredCredentials ? WebURLRequest::FetchCredentialsModeInclude : WebURLRe
quest::FetchCredentialsModeOmit); |
279 loadRequest(crossOriginRequest, crossOriginOptions); | 279 loadRequest(crossOriginRequest, crossOriginOptions); |
280 // |this| may be dead here in async mode. | 280 // |this| may be dead here in async mode. |
281 } else { | 281 } else { |
282 m_crossOriginNonSimpleRequest = true; | 282 m_crossOriginNonSimpleRequest = true; |
283 | 283 |
284 ResourceRequest crossOriginRequest(request); | 284 ResourceRequest crossOriginRequest(request); |
285 ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); | 285 ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); |
286 // Do not set the Origin header for preflight requests. | 286 // Do not set the Origin header for preflight requests. |
287 updateRequestForAccessControl(crossOriginRequest, 0, effectiveAllowCrede
ntials()); | 287 updateRequestForAccessControl(crossOriginRequest, 0, effectiveAllowCrede
ntials()); |
288 // We update the credentials mode according to effectiveAllowCredentials
() here for backward compatibility. But this is not correct. | 288 // We update the credentials mode according to effectiveAllowCredentials
() here for backward compatibility. But this is not correct. |
289 // FIXME: We should set it in the caller of DocumentThreadableLoader. | 289 // FIXME: We should set it in the caller of DocumentThreadableLoader. |
290 crossOriginRequest.setFetchCredentialsMode(effectiveAllowCredentials() =
= AllowStoredCredentials ? WebURLRequest::FetchCredentialsModeInclude : WebURLRe
quest::FetchCredentialsModeOmit); | 290 crossOriginRequest.setFetchCredentialsMode(effectiveAllowCredentials() =
= AllowStoredCredentials ? WebURLRequest::FetchCredentialsModeInclude : WebURLRe
quest::FetchCredentialsModeOmit); |
291 m_actualRequest = crossOriginRequest; | 291 m_actualRequest = crossOriginRequest; |
292 m_actualOptions = crossOriginOptions; | 292 m_actualOptions = crossOriginOptions; |
293 | 293 |
294 bool shouldForcePreflight = InspectorInstrumentation::shouldForceCORSPre
flight(m_document); | 294 bool shouldForcePreflight = InspectorInstrumentation::shouldForceCORSPre
flight(m_document); |
295 bool canSkipPreflight = CrossOriginPreflightResultCache::shared().canSki
pPreflight(securityOrigin()->toString(), m_actualRequest.url(), effectiveAllowCr
edentials(), m_actualRequest.httpMethod(), m_actualRequest.httpHeaderFields()); | 295 bool canSkipPreflight = CrossOriginPreflightResultCache::shared().canSki
pPreflight(getSecurityOrigin()->toString(), m_actualRequest.url(), effectiveAllo
wCredentials(), m_actualRequest.httpMethod(), m_actualRequest.httpHeaderFields()
); |
296 if (canSkipPreflight && !shouldForcePreflight) { | 296 if (canSkipPreflight && !shouldForcePreflight) { |
297 loadActualRequest(); | 297 loadActualRequest(); |
298 // |this| may be dead here in async mode. | 298 // |this| may be dead here in async mode. |
299 } else { | 299 } else { |
300 ResourceRequest preflightRequest = createAccessControlPreflightReque
st(m_actualRequest, securityOrigin()); | 300 ResourceRequest preflightRequest = createAccessControlPreflightReque
st(m_actualRequest, getSecurityOrigin()); |
301 // Create a ResourceLoaderOptions for preflight. | 301 // Create a ResourceLoaderOptions for preflight. |
302 ResourceLoaderOptions preflightOptions = m_actualOptions; | 302 ResourceLoaderOptions preflightOptions = m_actualOptions; |
303 preflightOptions.allowCredentials = DoNotAllowStoredCredentials; | 303 preflightOptions.allowCredentials = DoNotAllowStoredCredentials; |
304 loadRequest(preflightRequest, preflightOptions); | 304 loadRequest(preflightRequest, preflightOptions); |
305 // |this| may be dead here in async mode. | 305 // |this| may be dead here in async mode. |
306 } | 306 } |
307 } | 307 } |
308 } | 308 } |
309 | 309 |
310 DocumentThreadableLoader::~DocumentThreadableLoader() | 310 DocumentThreadableLoader::~DocumentThreadableLoader() |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 String accessControlErrorDescription; | 468 String accessControlErrorDescription; |
469 | 469 |
470 // Non-simple cross origin requests (both preflight and actual one) are | 470 // Non-simple cross origin requests (both preflight and actual one) are |
471 // not allowed to follow redirect. | 471 // not allowed to follow redirect. |
472 if (m_crossOriginNonSimpleRequest) { | 472 if (m_crossOriginNonSimpleRequest) { |
473 accessControlErrorDescription = "The request was redirected to '"+ r
equest.url().getString() + "', which is disallowed for cross-origin requests tha
t require preflight."; | 473 accessControlErrorDescription = "The request was redirected to '"+ r
equest.url().getString() + "', which is disallowed for cross-origin requests tha
t require preflight."; |
474 } else { | 474 } else { |
475 // The redirect response must pass the access control check if the | 475 // The redirect response must pass the access control check if the |
476 // original request was not same-origin. | 476 // original request was not same-origin. |
477 allowRedirect = CrossOriginAccessControl::isLegalRedirectLocation(re
quest.url(), accessControlErrorDescription) | 477 allowRedirect = CrossOriginAccessControl::isLegalRedirectLocation(re
quest.url(), accessControlErrorDescription) |
478 && (m_sameOriginRequest || passesAccessControlCheck(redirectResp
onse, effectiveAllowCredentials(), securityOrigin(), accessControlErrorDescripti
on, m_requestContext)); | 478 && (m_sameOriginRequest || passesAccessControlCheck(redirectResp
onse, effectiveAllowCredentials(), getSecurityOrigin(), accessControlErrorDescri
ption, m_requestContext)); |
479 } | 479 } |
480 | 480 |
481 if (allowRedirect) { | 481 if (allowRedirect) { |
482 // FIXME: consider combining this with CORS redirect handling perfor
med by | 482 // FIXME: consider combining this with CORS redirect handling perfor
med by |
483 // CrossOriginAccessControl::handleRedirect(). | 483 // CrossOriginAccessControl::handleRedirect(). |
484 clearResource(); | 484 clearResource(); |
485 | 485 |
486 RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::create(redir
ectResponse.url()); | 486 RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::create(redir
ectResponse.url()); |
487 RefPtr<SecurityOrigin> requestOrigin = SecurityOrigin::create(reques
t.url()); | 487 RefPtr<SecurityOrigin> requestOrigin = SecurityOrigin::create(reques
t.url()); |
488 // If the original request wasn't same-origin, then if the request U
RL origin is not same origin with the original URL origin, | 488 // If the original request wasn't same-origin, then if the request U
RL origin is not same origin with the original URL origin, |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 m_isUsingDataConsumerHandle = true; | 564 m_isUsingDataConsumerHandle = true; |
565 | 565 |
566 handleResponse(resource->identifier(), response, handle); | 566 handleResponse(resource->identifier(), response, handle); |
567 // |this| may be dead here. | 567 // |this| may be dead here. |
568 } | 568 } |
569 | 569 |
570 void DocumentThreadableLoader::handlePreflightResponse(const ResourceResponse& r
esponse) | 570 void DocumentThreadableLoader::handlePreflightResponse(const ResourceResponse& r
esponse) |
571 { | 571 { |
572 String accessControlErrorDescription; | 572 String accessControlErrorDescription; |
573 | 573 |
574 if (!passesAccessControlCheck(response, effectiveAllowCredentials(), securit
yOrigin(), accessControlErrorDescription, m_requestContext)) { | 574 if (!passesAccessControlCheck(response, effectiveAllowCredentials(), getSecu
rityOrigin(), accessControlErrorDescription, m_requestContext)) { |
575 handlePreflightFailure(response.url().getString(), "Response to prefligh
t request doesn't pass access control check: " + accessControlErrorDescription); | 575 handlePreflightFailure(response.url().getString(), "Response to prefligh
t request doesn't pass access control check: " + accessControlErrorDescription); |
576 // |this| may be dead here in async mode. | 576 // |this| may be dead here in async mode. |
577 return; | 577 return; |
578 } | 578 } |
579 | 579 |
580 if (!passesPreflightStatusCheck(response, accessControlErrorDescription)) { | 580 if (!passesPreflightStatusCheck(response, accessControlErrorDescription)) { |
581 handlePreflightFailure(response.url().getString(), accessControlErrorDes
cription); | 581 handlePreflightFailure(response.url().getString(), accessControlErrorDes
cription); |
582 // |this| may be dead here in async mode. | 582 // |this| may be dead here in async mode. |
583 return; | 583 return; |
584 } | 584 } |
585 | 585 |
586 OwnPtr<CrossOriginPreflightResultCacheItem> preflightResult = adoptPtr(new C
rossOriginPreflightResultCacheItem(effectiveAllowCredentials())); | 586 OwnPtr<CrossOriginPreflightResultCacheItem> preflightResult = adoptPtr(new C
rossOriginPreflightResultCacheItem(effectiveAllowCredentials())); |
587 if (!preflightResult->parse(response, accessControlErrorDescription) | 587 if (!preflightResult->parse(response, accessControlErrorDescription) |
588 || !preflightResult->allowsCrossOriginMethod(m_actualRequest.httpMethod(
), accessControlErrorDescription) | 588 || !preflightResult->allowsCrossOriginMethod(m_actualRequest.httpMethod(
), accessControlErrorDescription) |
589 || !preflightResult->allowsCrossOriginHeaders(m_actualRequest.httpHeader
Fields(), accessControlErrorDescription)) { | 589 || !preflightResult->allowsCrossOriginHeaders(m_actualRequest.httpHeader
Fields(), accessControlErrorDescription)) { |
590 handlePreflightFailure(response.url().getString(), accessControlErrorDes
cription); | 590 handlePreflightFailure(response.url().getString(), accessControlErrorDes
cription); |
591 // |this| may be dead here in async mode. | 591 // |this| may be dead here in async mode. |
592 return; | 592 return; |
593 } | 593 } |
594 | 594 |
595 CrossOriginPreflightResultCache::shared().appendEntry(securityOrigin()->toSt
ring(), m_actualRequest.url(), preflightResult.release()); | 595 CrossOriginPreflightResultCache::shared().appendEntry(getSecurityOrigin()->t
oString(), m_actualRequest.url(), preflightResult.release()); |
596 } | 596 } |
597 | 597 |
598 void DocumentThreadableLoader::reportResponseReceived(unsigned long identifier,
const ResourceResponse& response) | 598 void DocumentThreadableLoader::reportResponseReceived(unsigned long identifier,
const ResourceResponse& response) |
599 { | 599 { |
600 LocalFrame* frame = document().frame(); | 600 LocalFrame* frame = document().frame(); |
601 // We are seeing crashes caused by nullptr (crbug.com/578849). But the frame | 601 // We are seeing crashes caused by nullptr (crbug.com/578849). But the frame |
602 // must be set here. TODO(horo): Find the root cause of the unset frame. | 602 // must be set here. TODO(horo): Find the root cause of the unset frame. |
603 ASSERT(frame); | 603 ASSERT(frame); |
604 if (!frame) | 604 if (!frame) |
605 return; | 605 return; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 | 639 |
640 // Even if the request met the conditions to get handled by a Service Worker | 640 // Even if the request met the conditions to get handled by a Service Worker |
641 // in the constructor of this class (and therefore | 641 // in the constructor of this class (and therefore |
642 // |m_fallbackRequestForServiceWorker| is set), the Service Worker may skip | 642 // |m_fallbackRequestForServiceWorker| is set), the Service Worker may skip |
643 // processing the request. Only if the request is same origin, the skipped | 643 // processing the request. Only if the request is same origin, the skipped |
644 // response may come here (wasFetchedViaServiceWorker() returns false) since | 644 // response may come here (wasFetchedViaServiceWorker() returns false) since |
645 // such a request doesn't have to go through the CORS algorithm by calling | 645 // such a request doesn't have to go through the CORS algorithm by calling |
646 // loadFallbackRequestForServiceWorker(). | 646 // loadFallbackRequestForServiceWorker(). |
647 // FIXME: We should use |m_sameOriginRequest| when we will support | 647 // FIXME: We should use |m_sameOriginRequest| when we will support |
648 // Suborigins (crbug.com/336894) for Service Worker. | 648 // Suborigins (crbug.com/336894) for Service Worker. |
649 ASSERT(m_fallbackRequestForServiceWorker.isNull() || securityOrigin()->canRe
quest(m_fallbackRequestForServiceWorker.url())); | 649 ASSERT(m_fallbackRequestForServiceWorker.isNull() || getSecurityOrigin()->ca
nRequest(m_fallbackRequestForServiceWorker.url())); |
650 m_fallbackRequestForServiceWorker = ResourceRequest(); | 650 m_fallbackRequestForServiceWorker = ResourceRequest(); |
651 | 651 |
652 if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == UseAccessC
ontrol) { | 652 if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == UseAccessC
ontrol) { |
653 String accessControlErrorDescription; | 653 String accessControlErrorDescription; |
654 if (!passesAccessControlCheck(response, effectiveAllowCredentials(), sec
urityOrigin(), accessControlErrorDescription, m_requestContext)) { | 654 if (!passesAccessControlCheck(response, effectiveAllowCredentials(), get
SecurityOrigin(), accessControlErrorDescription, m_requestContext)) { |
655 reportResponseReceived(identifier, response); | 655 reportResponseReceived(identifier, response); |
656 | 656 |
657 ThreadableLoaderClient* client = m_client; | 657 ThreadableLoaderClient* client = m_client; |
658 clear(); | 658 clear(); |
659 client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInte
rnal, 0, response.url().getString(), accessControlErrorDescription)); | 659 client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInte
rnal, 0, response.url().getString(), accessControlErrorDescription)); |
660 // |this| may be dead here. | 660 // |this| may be dead here. |
661 return; | 661 return; |
662 } | 662 } |
663 } | 663 } |
664 | 664 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 // |this| may be dead here in async mode. | 765 // |this| may be dead here in async mode. |
766 } | 766 } |
767 | 767 |
768 void DocumentThreadableLoader::loadActualRequest() | 768 void DocumentThreadableLoader::loadActualRequest() |
769 { | 769 { |
770 ResourceRequest actualRequest = m_actualRequest; | 770 ResourceRequest actualRequest = m_actualRequest; |
771 ResourceLoaderOptions actualOptions = m_actualOptions; | 771 ResourceLoaderOptions actualOptions = m_actualOptions; |
772 m_actualRequest = ResourceRequest(); | 772 m_actualRequest = ResourceRequest(); |
773 m_actualOptions = ResourceLoaderOptions(); | 773 m_actualOptions = ResourceLoaderOptions(); |
774 | 774 |
775 actualRequest.setHTTPOrigin(securityOrigin()); | 775 actualRequest.setHTTPOrigin(getSecurityOrigin()); |
776 | 776 |
777 clearResource(); | 777 clearResource(); |
778 | 778 |
779 loadRequest(actualRequest, actualOptions); | 779 loadRequest(actualRequest, actualOptions); |
780 // |this| may be dead here in async mode. | 780 // |this| may be dead here in async mode. |
781 } | 781 } |
782 | 782 |
783 void DocumentThreadableLoader::handlePreflightFailure(const String& url, const S
tring& errorDescription) | 783 void DocumentThreadableLoader::handlePreflightFailure(const String& url, const S
tring& errorDescription) |
784 { | 784 { |
785 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); | 785 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
901 return; | 901 return; |
902 | 902 |
903 handleSuccessfulFinish(identifier, 0.0); | 903 handleSuccessfulFinish(identifier, 0.0); |
904 } | 904 } |
905 | 905 |
906 bool DocumentThreadableLoader::isAllowedRedirect(const KURL& url) const | 906 bool DocumentThreadableLoader::isAllowedRedirect(const KURL& url) const |
907 { | 907 { |
908 if (m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) | 908 if (m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) |
909 return true; | 909 return true; |
910 | 910 |
911 return m_sameOriginRequest && securityOrigin()->canRequest(url); | 911 return m_sameOriginRequest && getSecurityOrigin()->canRequest(url); |
912 } | 912 } |
913 | 913 |
914 bool DocumentThreadableLoader::isAllowedByContentSecurityPolicy(const KURL& url,
ContentSecurityPolicy::RedirectStatus redirectStatus) const | 914 bool DocumentThreadableLoader::isAllowedByContentSecurityPolicy(const KURL& url,
ContentSecurityPolicy::RedirectStatus redirectStatus) const |
915 { | 915 { |
916 if (m_options.contentSecurityPolicyEnforcement != EnforceContentSecurityPoli
cy) | 916 if (m_options.contentSecurityPolicyEnforcement != EnforceContentSecurityPoli
cy) |
917 return true; | 917 return true; |
918 | 918 |
919 return document().contentSecurityPolicy()->allowRequest(m_requestContext, ur
l, redirectStatus); | 919 return document().contentSecurityPolicy()->allowRequest(m_requestContext, ur
l, redirectStatus); |
920 } | 920 } |
921 | 921 |
922 StoredCredentials DocumentThreadableLoader::effectiveAllowCredentials() const | 922 StoredCredentials DocumentThreadableLoader::effectiveAllowCredentials() const |
923 { | 923 { |
924 if (m_forceDoNotAllowStoredCredentials) | 924 if (m_forceDoNotAllowStoredCredentials) |
925 return DoNotAllowStoredCredentials; | 925 return DoNotAllowStoredCredentials; |
926 return m_resourceLoaderOptions.allowCredentials; | 926 return m_resourceLoaderOptions.allowCredentials; |
927 } | 927 } |
928 | 928 |
929 SecurityOrigin* DocumentThreadableLoader::securityOrigin() const | 929 SecurityOrigin* DocumentThreadableLoader::getSecurityOrigin() const |
930 { | 930 { |
931 return m_securityOrigin ? m_securityOrigin.get() : document().securityOrigin
(); | 931 return m_securityOrigin ? m_securityOrigin.get() : document().getSecurityOri
gin(); |
932 } | 932 } |
933 | 933 |
934 Document& DocumentThreadableLoader::document() const | 934 Document& DocumentThreadableLoader::document() const |
935 { | 935 { |
936 ASSERT(m_document); | 936 ASSERT(m_document); |
937 return *m_document; | 937 return *m_document; |
938 } | 938 } |
939 | 939 |
940 } // namespace blink | 940 } // namespace blink |
OLD | NEW |