1 /*
2     Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
3     Copyright (C) 2001 Dirk Mueller <mueller@kde.org>
4     Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
5     Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
6 
7     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Library General Public
9     License as published by the Free Software Foundation; either
10     version 2 of the License, or (at your option) any later version.
11 
12     This library is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15     Library General Public License for more details.
16 
17     You should have received a copy of the GNU Library General Public License
18     along with this library; see the file COPYING.LIB.  If not, write to
19     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20     Boston, MA 02110-1301, USA.
21 
22     This class provides all functionality needed for loading images, style
23     sheets and html pages from the web. It has a memory cache for these objects.
24 */
25 
26 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_SCRIPT_RESOURCE_H_
27 #define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_SCRIPT_RESOURCE_H_
28 
29 #include <memory>
30 
31 #include "third_party/blink/renderer/bindings/core/v8/script_streamer.h"
32 #include "third_party/blink/renderer/core/core_export.h"
33 #include "third_party/blink/renderer/core/loader/resource/text_resource.h"
34 #include "third_party/blink/renderer/platform/bindings/parkable_string.h"
35 #include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h"
36 #include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
37 #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
38 #include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h"
39 
40 namespace blink {
41 
42 class FetchParameters;
43 class KURL;
44 class ResourceFetcher;
45 class SingleCachedMetadataHandler;
46 
47 // ScriptResource is a resource representing a JavaScript, either a classic or
48 // module script.
49 //
50 // In addition to loading the script, a ScriptResource can optionally stream the
51 // script to the JavaScript parser/compiler, using a ScriptStreamer. In this
52 // case, clients of the ScriptResource will not receive the finished
53 // notification until the streaming completes.
54 // Note: ScriptStreamer is only used for "classic" scripts, i.e. not modules.
55 //
56 // See also:
57 // https://docs.google.com/document/d/143GOPl_XVgLPFfO-31b_MdBcnjklLEX2OIg_6eN6fQ4
58 class CORE_EXPORT ScriptResource final : public TextResource {
59  public:
60   // The script resource will always try to start streaming if kAllowStreaming
61   // is passed in.
62   enum StreamingAllowed { kNoStreaming, kAllowStreaming };
63 
64   static ScriptResource* Fetch(FetchParameters&,
65                                ResourceFetcher*,
66                                ResourceClient*,
67                                StreamingAllowed);
68 
69   // Public for testing
70   static ScriptResource* CreateForTest(const KURL& url,
71                                        const WTF::TextEncoding& encoding);
72 
73   ScriptResource(const ResourceRequest&,
74                  const ResourceLoaderOptions&,
75                  const TextResourceDecoderOptions&,
76                  StreamingAllowed);
77   ~ScriptResource() override;
78 
79   void ResponseBodyReceived(
80       ResponseBodyLoaderDrainableInterface& body_loader,
81       scoped_refptr<base::SingleThreadTaskRunner> loader_task_runner) override;
82 
83   void Trace(Visitor*) const override;
84 
85   void OnMemoryDump(WebMemoryDumpLevelOfDetail,
86                     WebProcessMemoryDump*) const override;
87 
88   void SetSerializedCachedMetadata(mojo_base::BigBuffer data) override;
89 
90   const ParkableString& SourceText();
91 
92   // Get the resource's current text. This can return partial data, so should
93   // not be used outside of the inspector.
94   String TextForInspector() const;
95 
96   SingleCachedMetadataHandler* CacheHandler();
97 
98   // Gets the script streamer from the ScriptResource, clearing the resource's
99   // streamer so that it cannot be used twice.
100   ScriptStreamer* TakeStreamer();
101 
NoStreamerReason()102   ScriptStreamer::NotStreamingReason NoStreamerReason() const {
103     return no_streamer_reason_;
104   }
105 
106   // Used in DCHECKs
HasStreamer()107   bool HasStreamer() { return !!streamer_; }
HasRunningStreamer()108   bool HasRunningStreamer() { return streamer_ && !streamer_->IsFinished(); }
HasFinishedStreamer()109   bool HasFinishedStreamer() { return streamer_ && streamer_->IsFinished(); }
110 
111   // Visible for tests.
112   void SetRevalidatingRequest(const ResourceRequestHead&) override;
113 
114  protected:
115   CachedMetadataHandler* CreateCachedMetadataHandler(
116       std::unique_ptr<CachedMetadataSender> send_callback) override;
117 
118   void DestroyDecodedDataForFailedRevalidation() override;
119 
120   // ScriptResources are considered finished when either:
121   //   1. Loading + streaming completes, or
122   //   2. Loading completes + streaming is disabled.
123   void NotifyFinished() override;
124 
125  private:
126   // Valid state transitions:
127   //
128   //            kWaitingForDataPipe          DisableStreaming()
129   //                    |---------------------------.
130   //                    |                           |
131   //                    v                           v
132   //               kStreaming -----------------> kStreamingDisabled
133   //
134   enum class StreamingState {
135     // Streaming is allowed on this resource, but we're waiting to receive a
136     // data pipe.
137     kWaitingForDataPipe,
138     // The script streamer is active, and has the data pipe.
139     kStreaming,
140 
141     // Streaming was disabled, either manually or because we got a body with
142     // no data-pipe.
143     kStreamingDisabled,
144   };
145 
146   class ScriptResourceFactory : public ResourceFactory {
147    public:
ScriptResourceFactory(StreamingAllowed streaming_allowed)148     explicit ScriptResourceFactory(StreamingAllowed streaming_allowed)
149         : ResourceFactory(ResourceType::kScript,
150                           TextResourceDecoderOptions::kPlainTextContent),
151           streaming_allowed_(streaming_allowed) {}
152 
Create(const ResourceRequest & request,const ResourceLoaderOptions & options,const TextResourceDecoderOptions & decoder_options)153     Resource* Create(
154         const ResourceRequest& request,
155         const ResourceLoaderOptions& options,
156         const TextResourceDecoderOptions& decoder_options) const override {
157       return MakeGarbageCollected<ScriptResource>(
158           request, options, decoder_options, streaming_allowed_);
159     }
160 
161    private:
162     StreamingAllowed streaming_allowed_;
163   };
164 
165   bool CanUseCacheValidator() const override;
166 
167   void DisableStreaming(ScriptStreamer::NotStreamingReason no_streamer_reason);
168 
169   void AdvanceStreamingState(StreamingState new_state);
170 
171   // Check that invariants for the state hold.
172   void CheckStreamingState() const;
173 
174   void OnDataPipeReadable(MojoResult result,
175                           const mojo::HandleSignalsState& state);
176 
177   ParkableString source_text_;
178 
179   Member<ScriptStreamer> streamer_;
180   ScriptStreamer::NotStreamingReason no_streamer_reason_ =
181       ScriptStreamer::NotStreamingReason::kInvalid;
182   StreamingState streaming_state_ = StreamingState::kWaitingForDataPipe;
183 };
184 
185 DEFINE_RESOURCE_TYPE_CASTS(Script);
186 
187 }  // namespace blink
188 
189 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_SCRIPT_RESOURCE_H_
190