2
* Copyright 2012 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: rahulbansal@google.com (Rahul Bansal)
19
#ifndef NET_INSTAWEB_REWRITER_PUBLIC_SPLIT_HTML_FILTER_H_
20
#define NET_INSTAWEB_REWRITER_PUBLIC_SPLIT_HTML_FILTER_H_
24
#include "net/instaweb/rewriter/public/rewrite_driver.h"
25
#include "net/instaweb/rewriter/public/script_tag_scanner.h"
26
#include "net/instaweb/rewriter/public/server_context.h"
27
#include "net/instaweb/rewriter/public/suppress_prehead_filter.h"
28
#include "net/instaweb/util/public/basictypes.h"
29
#include "net/instaweb/util/public/json.h"
30
#include "net/instaweb/util/public/json_writer.h"
31
#include "net/instaweb/util/public/null_writer.h"
32
#include "net/instaweb/util/public/scoped_ptr.h"
33
#include "net/instaweb/util/public/string.h"
34
#include "net/instaweb/util/public/string_util.h"
36
namespace net_instaweb {
40
class SplitHtmlConfig;
42
class StaticAssetManager;
45
// Splits the incoming html content into above the fold html and below the
46
// fold json based on critical line specification stored in property cache.
48
// This filter will stream above the fold html and send below the fold json at
49
// EndDocument. It directly writes to the http request.
50
class SplitHtmlFilter : public SuppressPreheadFilter {
52
static const char kSplitSuffixJsFormatString[];
53
static const char kSplitTwoChunkSuffixJsFormatString[];
54
static const char kLoadHiResImages[];
55
static const char kMetaReferer[];
57
explicit SplitHtmlFilter(RewriteDriver* rewrite_driver);
58
virtual ~SplitHtmlFilter();
60
virtual void DetermineEnabled(GoogleString* disabled_reason);
62
virtual void StartDocument();
63
virtual void EndDocument();
65
virtual void StartElement(HtmlElement* element);
66
virtual void EndElement(HtmlElement* element);
68
static const GoogleString& GetBlinkJsUrl(
69
const RewriteOptions* options,
70
const StaticAssetManager* static_asset_manager);
72
virtual const char* Name() const { return "SplitHtmlFilter"; }
75
const SplitHtmlConfig* config() const {
76
return driver()->split_html_config();
78
const StaticAssetManager* static_asset_manager() const {
79
return driver()->server_context()->static_asset_manager();
82
void ServeNonCriticalPanelContents(const Json::Value& json);
84
// Sets panel-id attribute to the element. This is not used by client-side
86
void MarkElementWithPanelId(HtmlElement* element,
87
const GoogleString& panel_id);
89
// Reads the panel-id attribute and returns the value
90
GoogleString GetPanelIdForInstance(HtmlElement* element);
92
// Returns a string representation of the critical line config.
93
GoogleString GenerateCriticalLineConfigString();
95
// Pops the json from top of the stack and merges with parent panel which is
97
void EndPanelInstance();
99
// Pushes new Json to the top of the stack corresponding to element.
100
void StartPanelInstance(HtmlElement* element);
102
// Inserts <!-- GooglePanel begin --> and <!-- GooglePanel end --> stubs.
103
void InsertPanelStub(HtmlElement* element, const GoogleString& panel_id);
105
// Appends dict to the dictionary array
106
void AppendJsonData(Json::Value* dictionary, const Json::Value& dict);
108
void WriteString(const StringPiece& str);
110
// Inserts lazy load and other scripts needed for split initialization into
111
// the head element. If no head tag in the page, it inserts one before
113
void InsertSplitInitScripts(HtmlElement* element);
115
void InvokeBaseHtmlFilterStartDocument();
117
void InvokeBaseHtmlFilterStartElement(HtmlElement* element);
119
void InvokeBaseHtmlFilterEndElement(HtmlElement* element);
121
void InvokeBaseHtmlFilterEndDocument();
123
// Returns true, if the cross-origin is allowed by looking it up in
124
// RewriteOptions::access_control_allow_origins()
125
// Note: The cross-origin must match exactly inclusing the protocol.
126
// The only wildcard supported is '*' which means allow all domains.
127
bool IsAllowedCrossDomainRequest(StringPiece cross_origin);
129
scoped_ptr<SplitHtmlState> state_;
130
const RewriteOptions* options_;
131
std::vector<ElementJsonPair> element_json_stack_;
132
Json::FastWriter fast_writer_;
133
scoped_ptr<JsonWriter> json_writer_;
134
Writer* original_writer_;
135
NullWriter null_writer_;
137
bool script_written_;
138
bool flush_head_enabled_;
139
bool disable_filter_;
140
bool inside_pagespeed_no_defer_script_;
141
bool serve_response_in_two_chunks_;
142
int last_script_index_before_panel_stub_;
144
ScriptTagScanner script_tag_scanner_;
146
DISALLOW_COPY_AND_ASSIGN(SplitHtmlFilter);
149
} // namespace net_instaweb
151
#endif // NET_INSTAWEB_REWRITER_PUBLIC_SPLIT_HTML_FILTER_H_