1 /*
2  * Copyright (C) 2007, 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "third_party/blink/renderer/core/css/css_font_face_src_value.h"
27 
28 #include "base/feature_list.h"
29 #include "third_party/blink/public/common/features.h"
30 #include "third_party/blink/public/platform/web_url_request.h"
31 #include "third_party/blink/renderer/core/css/css_markup.h"
32 #include "third_party/blink/renderer/core/css/style_sheet_contents.h"
33 #include "third_party/blink/renderer/core/dom/document.h"
34 #include "third_party/blink/renderer/core/dom/node.h"
35 #include "third_party/blink/renderer/core/loader/resource/font_resource.h"
36 #include "third_party/blink/renderer/core/workers/worker_global_scope.h"
37 #include "third_party/blink/renderer/platform/fonts/font_cache.h"
38 #include "third_party/blink/renderer/platform/fonts/font_custom_platform_data.h"
39 #include "third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h"
40 #include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
41 #include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
42 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
43 #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
44 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
45 #include "third_party/blink/renderer/platform/weborigin/security_policy.h"
46 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
47 
48 namespace blink {
49 
IsSupportedFormat() const50 bool CSSFontFaceSrcValue::IsSupportedFormat() const {
51   // Normally we would just check the format, but in order to avoid conflicts
52   // with the old WinIE style of font-face, we will also check to see if the URL
53   // ends with .eot.  If so, we'll go ahead and assume that we shouldn't load
54   // it.
55   if (format_.IsEmpty()) {
56     return absolute_resource_.StartsWithIgnoringASCIICase("data:") ||
57            !absolute_resource_.EndsWithIgnoringASCIICase(".eot");
58   }
59 
60   return FontCustomPlatformData::SupportsFormat(format_);
61 }
62 
CustomCSSText() const63 String CSSFontFaceSrcValue::CustomCSSText() const {
64   StringBuilder result;
65   if (IsLocal()) {
66     result.Append("local(");
67     result.Append(SerializeString(absolute_resource_));
68     result.Append(')');
69   } else {
70     result.Append(SerializeURI(specified_resource_));
71   }
72   if (!format_.IsEmpty()) {
73     result.Append(" format(");
74     result.Append(SerializeString(format_));
75     result.Append(')');
76   }
77   return result.ToString();
78 }
79 
HasFailedOrCanceledSubresources() const80 bool CSSFontFaceSrcValue::HasFailedOrCanceledSubresources() const {
81   return fetched_ && fetched_->GetResource()->LoadFailedOrCanceled();
82 }
83 
Fetch(ExecutionContext * context,FontResourceClient * client) const84 FontResource& CSSFontFaceSrcValue::Fetch(ExecutionContext* context,
85                                          FontResourceClient* client) const {
86   if (!fetched_) {
87     ResourceRequest resource_request(absolute_resource_);
88     resource_request.SetReferrerPolicy(
89         ReferrerPolicyResolveDefault(referrer_.referrer_policy));
90     resource_request.SetReferrerString(referrer_.referrer);
91     ResourceLoaderOptions options;
92     options.initiator_info.name = fetch_initiator_type_names::kCSS;
93     FetchParameters params(std::move(resource_request), options);
94     if (base::FeatureList::IsEnabled(
95             features::kWebFontsCacheAwareTimeoutAdaption)) {
96       params.SetCacheAwareLoadingEnabled(kIsCacheAwareLoadingEnabled);
97     }
98     params.SetContentSecurityCheck(should_check_content_security_policy_);
99     params.SetFromOriginDirtyStyleSheet(origin_clean_ != OriginClean::kTrue);
100     const SecurityOrigin* security_origin = context->GetSecurityOrigin();
101 
102     // Local fonts are accessible from file: URLs even when
103     // allowFileAccessFromFileURLs is false.
104     if (!params.Url().IsLocalFile()) {
105       params.SetCrossOriginAccessControl(security_origin,
106                                          kCrossOriginAttributeAnonymous);
107     }
108     // For Workers, Fetcher is lazily loaded, so we must ensure it's available
109     // here.
110     if (auto* scope = DynamicTo<WorkerGlobalScope>(context)) {
111       scope->EnsureFetcher();
112     }
113     fetched_ = MakeGarbageCollected<FontResourceHelper>(
114         FontResource::Fetch(params, context->Fetcher(), client),
115         context->GetTaskRunner(TaskType::kInternalLoading).get());
116   } else {
117     // FIXME: CSSFontFaceSrcValue::Fetch is invoked when @font-face rule
118     // is processed by StyleResolver / StyleEngine.
119     RestoreCachedResourceIfNeeded(context);
120     if (client) {
121       client->SetResource(
122           fetched_->GetResource(),
123           context->GetTaskRunner(TaskType::kInternalLoading).get());
124     }
125   }
126   return *ToFontResource(fetched_->GetResource());
127 }
128 
RestoreCachedResourceIfNeeded(ExecutionContext * context) const129 void CSSFontFaceSrcValue::RestoreCachedResourceIfNeeded(
130     ExecutionContext* context) const {
131   DCHECK(fetched_);
132   DCHECK(context);
133   DCHECK(context->Fetcher());
134 
135   const String resource_url = context->CompleteURL(absolute_resource_);
136   DCHECK_EQ(should_check_content_security_policy_,
137             fetched_->GetResource()->Options().content_security_policy_option);
138   context->Fetcher()->EmulateLoadStartedForInspector(
139       fetched_->GetResource(), KURL(resource_url),
140       mojom::RequestContextType::FONT,
141       network::mojom::RequestDestination::kFont,
142       fetch_initiator_type_names::kCSS);
143 }
144 
Equals(const CSSFontFaceSrcValue & other) const145 bool CSSFontFaceSrcValue::Equals(const CSSFontFaceSrcValue& other) const {
146   return is_local_ == other.is_local_ && format_ == other.format_ &&
147          specified_resource_ == other.specified_resource_ &&
148          absolute_resource_ == other.absolute_resource_;
149 }
150 
151 }  // namespace blink
152