1 // Copyright 2019 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 "content/browser/service_worker/service_worker_loader_helpers.h"
6
7 #include "base/command_line.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/time/time.h"
10 #include "components/network_session_configurator/common/network_switches.h"
11 #include "content/browser/service_worker/service_worker_consts.h"
12 #include "third_party/blink/public/common/features.h"
13 #include "third_party/blink/public/common/mime_util/mime_util.h"
14 #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
15
16 namespace content {
17
18 namespace service_worker_loader_helpers {
19
CheckResponseHead(const network::mojom::URLResponseHead & response_head,blink::ServiceWorkerStatusCode * out_service_worker_status,network::URLLoaderCompletionStatus * out_completion_status,std::string * out_error_message)20 bool CheckResponseHead(
21 const network::mojom::URLResponseHead& response_head,
22 blink::ServiceWorkerStatusCode* out_service_worker_status,
23 network::URLLoaderCompletionStatus* out_completion_status,
24 std::string* out_error_message) {
25 if (response_head.headers->response_code() / 100 != 2) {
26 // Non-2XX HTTP status code is handled as an error.
27 *out_completion_status =
28 network::URLLoaderCompletionStatus(net::ERR_INVALID_RESPONSE);
29 *out_error_message = base::StringPrintf(
30 ServiceWorkerConsts::kServiceWorkerBadHTTPResponseError,
31 response_head.headers->response_code());
32 *out_service_worker_status = blink::ServiceWorkerStatusCode::kErrorNetwork;
33 return false;
34 }
35
36 if (net::IsCertStatusError(response_head.cert_status) &&
37 !base::CommandLine::ForCurrentProcess()->HasSwitch(
38 switches::kIgnoreCertificateErrors)) {
39 *out_completion_status = network::URLLoaderCompletionStatus(
40 net::MapCertStatusToNetError(response_head.cert_status));
41 *out_error_message = ServiceWorkerConsts::kServiceWorkerSSLError;
42 *out_service_worker_status = blink::ServiceWorkerStatusCode::kErrorNetwork;
43 return false;
44 }
45
46 // Remain consistent with logic in
47 // blink::InstalledServiceWorkerModuleScriptFetcher::Fetch()
48 if (!blink::IsSupportedJavascriptMimeType(response_head.mime_type) &&
49 !(base::FeatureList::IsEnabled(blink::features::kJSONModules) &&
50 blink::IsJSONMimeType(response_head.mime_type))) {
51 *out_completion_status =
52 network::URLLoaderCompletionStatus(net::ERR_INSECURE_RESPONSE);
53 *out_error_message =
54 response_head.mime_type.empty()
55 ? ServiceWorkerConsts::kServiceWorkerNoMIMEError
56 : base::StringPrintf(
57 ServiceWorkerConsts::kServiceWorkerBadMIMEError,
58 response_head.mime_type.c_str());
59 *out_service_worker_status = blink::ServiceWorkerStatusCode::kErrorSecurity;
60 return false;
61 }
62
63 return true;
64 }
65
ShouldBypassCacheDueToUpdateViaCache(bool is_main_script,blink::mojom::ServiceWorkerUpdateViaCache cache_mode)66 bool ShouldBypassCacheDueToUpdateViaCache(
67 bool is_main_script,
68 blink::mojom::ServiceWorkerUpdateViaCache cache_mode) {
69 switch (cache_mode) {
70 case blink::mojom::ServiceWorkerUpdateViaCache::kImports:
71 return is_main_script;
72 case blink::mojom::ServiceWorkerUpdateViaCache::kNone:
73 return true;
74 case blink::mojom::ServiceWorkerUpdateViaCache::kAll:
75 return false;
76 }
77 NOTREACHED() << static_cast<int>(cache_mode);
78 return false;
79 }
80
ShouldValidateBrowserCacheForScript(bool is_main_script,bool force_bypass_cache,blink::mojom::ServiceWorkerUpdateViaCache cache_mode,base::TimeDelta time_since_last_check)81 bool ShouldValidateBrowserCacheForScript(
82 bool is_main_script,
83 bool force_bypass_cache,
84 blink::mojom::ServiceWorkerUpdateViaCache cache_mode,
85 base::TimeDelta time_since_last_check) {
86 return (ShouldBypassCacheDueToUpdateViaCache(is_main_script, cache_mode) ||
87 time_since_last_check >
88 ServiceWorkerConsts::kServiceWorkerScriptMaxCacheAge ||
89 force_bypass_cache);
90 }
91
92 #if DCHECK_IS_ON()
CheckVersionStatusBeforeWorkerScriptLoad(ServiceWorkerVersion::Status status,network::mojom::RequestDestination resource_destination)93 void CheckVersionStatusBeforeWorkerScriptLoad(
94 ServiceWorkerVersion::Status status,
95 network::mojom::RequestDestination resource_destination) {
96 switch (resource_destination) {
97 // The service worker main script should be fetched during worker startup.
98 case network::mojom::RequestDestination::kServiceWorker:
99 DCHECK_EQ(status, ServiceWorkerVersion::NEW);
100 break;
101 // importScripts() should be called until completion of the install event.
102 case network::mojom::RequestDestination::kScript:
103 DCHECK(status == ServiceWorkerVersion::NEW ||
104 status == ServiceWorkerVersion::INSTALLING);
105 break;
106 default:
107 NOTREACHED() << resource_destination;
108 break;
109 }
110 }
111 #endif // DCHECK_IS_ON()
112
113 } // namespace service_worker_loader_helpers
114
115 } // namespace content
116