2
* Copyright 2010 Google Inc.
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
// Author: jmarantz@google.com (Joshua Marantz)
19
// Provides the ResourceCombiner class which helps implement filters that
20
// combine multiple resources, as well as the TimedBool, which is useful
21
// when figuring out how long results are valid for.
23
#ifndef NET_INSTAWEB_REWRITER_PUBLIC_RESOURCE_COMBINER_H_
24
#define NET_INSTAWEB_REWRITER_PUBLIC_RESOURCE_COMBINER_H_
26
#include "net/instaweb/rewriter/public/resource.h"
27
#include "net/instaweb/rewriter/public/server_context.h"
28
#include "net/instaweb/rewriter/public/url_partnership.h"
29
#include "net/instaweb/util/public/basictypes.h"
30
#include "net/instaweb/util/public/gtest_prod.h"
31
#include "net/instaweb/util/public/string.h"
32
#include "net/instaweb/util/public/string_util.h"
34
namespace net_instaweb {
43
// A boolean with an expiration date.
45
// A date, in milliseconds since the epoch, after which value should
46
// no longer be considered valid.
51
// This class is a utility for filters that combine multiple resource
52
// files into one. It provides two major pieces of functionality to help out:
53
// 1) It keeps a ResourceVector and provides methods to keep track
54
// of resources and URLs that can be safely combined together while
55
// encoding the information on the pieces in the combined URL.
56
// 2) It implements Fetch, reconstructing combinations as needed.
57
class ResourceCombiner {
59
// Slack to leave in URL size, so that other filters running afterwards
60
// can expand the URLs without going over maximum allowed sizes.
62
// Why 100? First example I saw, CssFilter expanded a CssCombined URL
63
// by 36 chars. So 100 seemed like a nice round number to allow two
64
// filters to run after this and then for there still be a little slack.
66
// TODO(sligocki): Set this more intelligently.
67
static const int kUrlSlack = 100;
69
// Note: extension should not include the leading dot here.
70
ResourceCombiner(RewriteDriver* rewrite_driver,
71
const StringPiece& extension,
72
RewriteFilter* filter);
74
virtual ~ResourceCombiner();
76
// Resets the current combiner to an empty state, incorporating the base URL.
77
// Make sure this gets called before documents --- on a ::Flush() is enough.
78
// If a subclass needs to do some of its own reseting, see Clear().
81
// Computes a name for the URL that meets all known character-set and
83
GoogleString UrlSafeId() const;
85
// Returns the number of URLs that have been successfully added.
86
int num_urls() const { return partnership_.num_urls(); }
88
const ResourceVector& resources() const { return resources_; }
90
// Base common to all URLs. Always has a trailing slash.
91
GoogleString ResolvedBase() const { return partnership_.ResolvedBase(); }
93
// TODO(jmarantz): rename this to AddResource now that async flow is live.
94
TimedBool AddResourceNoFetch(const ResourcePtr& resource,
95
MessageHandler* handler);
98
// Removes the last resource that was added here, assuming the last call to
99
// AddResource was successful. If the last call to AddResource returned
100
// false, behavior is undefined.
101
virtual void RemoveLastResource();
103
// Returns one resource containing the combination of all added resources,
104
// creating it if necessary. Caller takes ownership. Returns NULL if the
105
// combination does not exist and cannot be created. Will not combine fewer
107
OutputResourcePtr Combine(MessageHandler* handler);
109
// Override this if your combination is not a matter of combining
110
// text pieces (perhaps adjusted by WritePiece).
111
virtual bool WriteCombination(const ResourceVector& combine_resources,
112
const OutputResourcePtr& combination,
113
MessageHandler* handler);
115
// Override this to alter how pieces are processed when included inside
116
// a combination. Returns whether successful. The default implementation
117
// writes input->contents() to the writer without any alteration.
118
// 'index' is the position of this piece in the combination.
119
virtual bool WritePiece(int index, const Resource* input,
120
OutputResource* combination, Writer* writer,
121
MessageHandler* handler);
123
// Override this if you need to remove some state whenever Reset() is called.
124
// Your implementation must call the superclass.
125
virtual void Clear();
127
ServerContext* const server_context_;
128
RewriteDriver* const rewrite_driver_;
131
friend class AggregateCombiner;
133
// Implement this to control the content-type given the combination.
134
virtual const ContentType* CombinationContentType() = 0;
136
// Recomputes the leaf size if our base has changed
137
void UpdateResolvedBase();
139
// Computes the total size
140
void ComputeLeafSize();
142
// Incrementally updates the accumulated leaf size without re-examining
143
// every element in the combined file.
144
void AccumulateLeafSize(const StringPiece& url);
146
// Determines whether our accumulated leaf size is too big, taking into
147
// account both per-segment and total-url limitations.
150
// Computes the total combined resources size.
151
// Override this if combined resource size to be restricted to some limit.
152
virtual void AccumulateCombinedSize(const ResourcePtr& resource) {}
154
// Determines whether our accumulated resources size is too big.
155
// Override this if combined resource size to be restricted to some limit.
156
virtual bool ContentSizeTooBig() const { return false; }
158
// Override this if you need to forbid some combinations based on the
159
// content of the resource (e.g. with resource->HttpStatusOk())
160
// This is called before the URL is added to UrlPartnership's
161
// data structures. If the method returns false, it should set
162
// *failure_reason to a user-comprehensible explanation.
163
virtual bool ResourceCombinable(Resource* resource,
164
GoogleString* failure_reason,
165
MessageHandler* handler);
167
UrlPartnership partnership_;
168
ResourceVector resources_;
169
StringVector multipart_encoder_urls_;
170
int prev_num_components_;
171
int accumulated_leaf_size_;
172
GoogleString resolved_base_;
173
const int url_overhead_;
174
RewriteFilter* filter_;
176
FRIEND_TEST(ResourceCombinerTest, TestRemove);
177
FRIEND_TEST(ResourceCombinerTest, TestRemoveFrom3);
178
FRIEND_TEST(ResourceCombinerTest, TestRebaseRemove);
179
FRIEND_TEST(ResourceCombinerTest, TestRebaseRemoveAdd);
181
DISALLOW_COPY_AND_ASSIGN(ResourceCombiner);
184
} // namespace net_instaweb
186
#endif // NET_INSTAWEB_REWRITER_PUBLIC_RESOURCE_COMBINER_H_