00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00018
00019 #ifndef NET_INSTAWEB_REWRITER_PUBLIC_CSS_FILTER_H_
00020 #define NET_INSTAWEB_REWRITER_PUBLIC_CSS_FILTER_H_
00021
00022 #include "base/scoped_ptr.h"
00023 #include "net/instaweb/htmlparse/public/html_element.h"
00024 #include "net/instaweb/rewriter/public/css_hierarchy.h"
00025 #include "net/instaweb/rewriter/public/css_resource_slot.h"
00026 #include "net/instaweb/rewriter/public/css_url_encoder.h"
00027 #include "net/instaweb/rewriter/public/output_resource_kind.h"
00028 #include "net/instaweb/rewriter/public/resource.h"
00029 #include "net/instaweb/rewriter/public/resource_manager.h"
00030 #include "net/instaweb/rewriter/public/resource_slot.h"
00031 #include "net/instaweb/rewriter/public/rewrite_driver.h"
00032 #include "net/instaweb/rewriter/public/rewrite_filter.h"
00033 #include "net/instaweb/rewriter/public/rewrite_options.h"
00034 #include "net/instaweb/rewriter/public/single_rewrite_context.h"
00035 #include "net/instaweb/util/public/basictypes.h"
00036 #include "net/instaweb/util/public/google_url.h"
00037 #include "net/instaweb/util/public/string.h"
00038 #include "net/instaweb/util/public/string_util.h"
00039
00040 namespace Css {
00041
00042 class Stylesheet;
00043
00044 }
00045
00046 namespace net_instaweb {
00047
00048 class CssImageRewriter;
00049 class CacheExtender;
00050 class HtmlCharactersNode;
00051 class ImageCombineFilter;
00052 class ImageRewriteFilter;
00053 class MessageHandler;
00054 class OutputPartitions;
00055 class ResourceContext;
00056 class RewriteContext;
00057 class Statistics;
00058 class UrlSegmentEncoder;
00059 class Variable;
00060 class Writer;
00061
00072 class CssFilter : public RewriteFilter {
00073 public:
00074 class Context;
00075
00076 CssFilter(RewriteDriver* driver,
00079 CacheExtender* cache_extender,
00080 ImageRewriteFilter* image_rewriter,
00081 ImageCombineFilter* image_combiner);
00082 virtual ~CssFilter();
00083
00084 static void Initialize(Statistics* statistics);
00085 static void Terminate();
00086
00090 static void InitializeAtExitManager();
00091
00092 virtual void StartDocumentImpl();
00093 virtual void StartElementImpl(HtmlElement* element);
00094 virtual void Characters(HtmlCharactersNode* characters);
00095 virtual void EndElementImpl(HtmlElement* element);
00096
00097 virtual const char* Name() const { return "CssFilter"; }
00098 virtual const char* id() const { return RewriteOptions::kCssFilterId; }
00099 virtual int FilterCacheFormatVersion() const;
00100
00101 static const char kBlocksRewritten[];
00102 static const char kParseFailures[];
00103 static const char kRewritesDropped[];
00104 static const char kTotalBytesSaved[];
00105 static const char kTotalOriginalBytes[];
00106 static const char kUses[];
00107
00108 RewriteContext* MakeNestedFlatteningContextInNewSlot(
00109 const ResourcePtr& resource, const GoogleString& location,
00110 CssFilter::Context* rewriter, RewriteContext* parent,
00111 CssHierarchy* hierarchy);
00112
00113 protected:
00114 virtual RewriteContext* MakeRewriteContext();
00115 virtual const UrlSegmentEncoder* encoder() const;
00116 virtual RewriteContext* MakeNestedRewriteContext(
00117 RewriteContext* parent, const ResourceSlotPtr& slot);
00118
00119 private:
00120 friend class Context;
00121
00122 Context* MakeContext(RewriteDriver* driver,
00123 RewriteContext* parent);
00124
00127 void StartInlineRewrite(HtmlElement* style_element, HtmlCharactersNode* text);
00128
00131 void StartAttributeRewrite(HtmlElement* element,
00132 HtmlElement::Attribute* style);
00133
00136 void StartExternalRewrite(HtmlElement* link, HtmlElement::Attribute* src);
00137
00138 ResourceSlot* MakeSlotForInlineCss(const StringPiece& content);
00139 CssFilter::Context* StartRewriting(const ResourceSlotPtr& slot);
00140
00146 bool GetApplicableCharset(const HtmlElement* element,
00147 GoogleString* charset) const;
00148
00151 bool GetApplicableMedia(const HtmlElement* element,
00152 StringVector* media) const;
00153
00154 bool in_style_element_;
00155
00156 HtmlElement* style_element_;
00157 HtmlCharactersNode* style_char_node_;
00158
00160 GoogleString meta_tag_charset_;
00161
00163 CacheExtender* cache_extender_;
00164 ImageRewriteFilter* image_rewrite_filter_;
00165 ImageCombineFilter* image_combiner_;
00166
00170 Variable* num_blocks_rewritten_;
00172 Variable* num_parse_failures_;
00175 Variable* num_rewrites_dropped_;
00181 Variable* total_bytes_saved_;
00185 Variable* total_original_bytes_;
00188 Variable* num_uses_;
00189
00190 CssUrlEncoder encoder_;
00191
00192 DISALLOW_COPY_AND_ASSIGN(CssFilter);
00193 };
00194
00196 class CssFilter::Context : public SingleRewriteContext {
00197 public:
00198 Context(CssFilter* filter, RewriteDriver* driver,
00199 RewriteContext* parent,
00200 CacheExtender* cache_extender,
00201 ImageRewriteFilter* image_rewriter,
00202 ImageCombineFilter* image_combiner,
00203 ResourceContext* context);
00204 virtual ~Context();
00205
00207 void SetupInlineRewrite(HtmlElement* style_element, HtmlCharactersNode* text);
00208 void SetupAttributeRewrite(HtmlElement* element, HtmlElement::Attribute* src);
00209 void SetupExternalRewrite(const GoogleUrl& base_gurl,
00210 const GoogleUrl& trim_gurl);
00211
00212 void RewriteCssFromNested(RewriteContext* parent, CssHierarchy* hierarchy);
00213
00216 virtual bool AbsolutifyIfNeeded(const StringPiece& input_contents,
00217 Writer* writer, MessageHandler* handler);
00218
00219 CssResourceSlotFactory* slot_factory() { return &slot_factory_; }
00220
00221 CssHierarchy* mutable_hierarchy() { return &hierarchy_; }
00222
00223 protected:
00224 virtual void Render();
00225 virtual void Harvest();
00226 virtual bool Partition(OutputPartitions* partitions,
00227 OutputResourceVector* outputs);
00228 virtual void RewriteSingle(const ResourcePtr& input,
00229 const OutputResourcePtr& output);
00230 virtual const char* id() const { return filter_->id(); }
00231 virtual OutputResourceKind kind() const { return kRewrittenResource; }
00232 virtual GoogleString CacheKeySuffix() const;
00233 virtual const UrlSegmentEncoder* encoder() const;
00234
00235 private:
00236 bool RewriteCssText(const GoogleUrl& css_base_gurl,
00237 const GoogleUrl& css_trim_gurl,
00238 const StringPiece& in_text,
00239 int64 in_text_size,
00240 bool text_is_declarations,
00241 MessageHandler* handler);
00243 void RewriteCssFromRoot(const StringPiece& in_text, int64 in_text_size,
00244 bool has_unparseables, Css::Stylesheet* stylesheet);
00245
00248 bool SerializeCss(int64 in_text_size,
00249 const Css::Stylesheet* stylesheet,
00250 const GoogleUrl& css_base_gurl,
00251 const GoogleUrl& css_trim_gurl,
00252 bool previously_optimized,
00253 bool stylesheet_is_declarations,
00254 bool add_utf8_bom,
00255 GoogleString* out_text,
00256 MessageHandler* handler);
00257
00261 bool IsInlineAttribute() const {
00262 return (rewrite_inline_attribute_ != NULL);
00263 }
00264
00268 int64 ImageInlineMaxBytes() const {
00269 if (rewrite_inline_element_ != NULL) {
00271 return driver_->options()->ImageInlineMaxBytes();
00272 } else {
00274 return driver_->options()->CssImageInlineMaxBytes();
00275 }
00276 }
00277
00278 CssFilter* filter_;
00279 RewriteDriver* driver_;
00280 scoped_ptr<CssImageRewriter> css_image_rewriter_;
00281 CssResourceSlotFactory slot_factory_;
00282 CssHierarchy hierarchy_;
00283 bool css_rewritten_;
00284 bool has_utf8_bom_;
00285
00289 HtmlElement* rewrite_inline_element_;
00290
00292 HtmlCharactersNode* rewrite_inline_char_node_;
00293
00297 HtmlElement::Attribute* rewrite_inline_attribute_;
00298
00300 int64 in_text_size_;
00301 GoogleUrl css_base_gurl_;
00302 GoogleUrl css_trim_gurl_;
00303 ResourcePtr input_resource_;
00304 OutputResourcePtr output_resource_;
00305
00306 DISALLOW_COPY_AND_ASSIGN(Context);
00307 };
00308
00309 }
00310
00311 #endif ///< NET_INSTAWEB_REWRITER_PUBLIC_CSS_FILTER_H_