| /* |
| * Copyright 2012 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| // Author: sriharis@google.com (Srihari Sukumaran) |
| |
| #include "net/instaweb/rewriter/public/support_noscript_filter.h" |
| |
| #include "net/instaweb/public/global_constants.h" |
| #include "net/instaweb/rewriter/public/mobilize_rewrite_filter.h" |
| #include "net/instaweb/rewriter/public/request_properties.h" |
| #include "net/instaweb/rewriter/public/rewrite_driver.h" |
| #include "net/instaweb/rewriter/public/rewrite_options.h" |
| #include "net/instaweb/rewriter/public/rewrite_query.h" |
| #include "net/instaweb/rewriter/public/split_html_beacon_filter.h" |
| #include "pagespeed/kernel/base/scoped_ptr.h" |
| #include "pagespeed/kernel/base/string.h" |
| #include "pagespeed/kernel/base/string_util.h" |
| #include "pagespeed/kernel/html/html_element.h" |
| #include "pagespeed/kernel/html/html_keywords.h" |
| #include "pagespeed/kernel/html/html_name.h" |
| #include "pagespeed/kernel/html/html_node.h" |
| #include "pagespeed/kernel/http/google_url.h" |
| |
| namespace net_instaweb { |
| |
| SupportNoscriptFilter::SupportNoscriptFilter(RewriteDriver* rewrite_driver) |
| : rewrite_driver_(rewrite_driver), |
| should_insert_noscript_(true) { |
| } |
| |
| SupportNoscriptFilter::~SupportNoscriptFilter() { |
| } |
| |
| void SupportNoscriptFilter::DetermineEnabled(GoogleString* disabled_reason) { |
| // Insert a NOSCRIPT tag only if at least one of the filters requiring |
| // JavaScript for execution is enabled. |
| should_insert_noscript_ = IsAnyFilterRequiringScriptExecutionEnabled(); |
| set_is_enabled(should_insert_noscript_); |
| } |
| |
| void SupportNoscriptFilter::StartElement(HtmlElement* element) { |
| if (should_insert_noscript_ && element->keyword() == HtmlName::kBody) { |
| scoped_ptr<GoogleUrl> url_with_psa_off( |
| rewrite_driver_->google_url().CopyAndAddQueryParam( |
| RewriteQuery::kPageSpeed, RewriteQuery::kNoscriptValue)); |
| GoogleString escaped_url; |
| HtmlKeywords::Escape(url_with_psa_off->Spec(), &escaped_url); |
| // TODO(sriharis): Replace the usage of HtmlCharactersNode with HtmlElement |
| // and Attribute. |
| HtmlCharactersNode* noscript_node = rewrite_driver_->NewCharactersNode( |
| element, StringPrintf(kNoScriptRedirectFormatter, |
| escaped_url.c_str(), escaped_url.c_str())); |
| rewrite_driver_->PrependChild(element, noscript_node); |
| should_insert_noscript_ = false; |
| } |
| // TODO(sriharis): Handle the case where there is no body -- insert a body in |
| // EndElement of kHtml? |
| } |
| |
| bool SupportNoscriptFilter::IsAnyFilterRequiringScriptExecutionEnabled() const { |
| const RewriteOptions* options = rewrite_driver_->options(); |
| const RequestProperties* request_properties = |
| rewrite_driver_->request_properties(); |
| RewriteOptions::FilterVector js_filters; |
| options->GetEnabledFiltersRequiringScriptExecution(&js_filters); |
| for (int i = 0, n = js_filters.size(); i < n; ++i) { |
| RewriteOptions::Filter filter = js_filters[i]; |
| bool filter_enabled = true; |
| switch (filter) { |
| case RewriteOptions::kDeferIframe: |
| case RewriteOptions::kDeferJavascript: |
| case RewriteOptions::kSplitHtml: |
| // We don't need to insert a noscript redirect if we are just |
| // instrumenting the page, instead of actually running split HTML. |
| filter_enabled = |
| (request_properties->SupportsJsDefer( |
| options->enable_aggressive_rewriters_for_mobile()) && |
| !SplitHtmlBeaconFilter::ShouldApply(rewrite_driver_)); |
| break; |
| case RewriteOptions::kDedupInlinedImages: |
| case RewriteOptions::kDelayImages: |
| case RewriteOptions::kLazyloadImages: |
| case RewriteOptions::kLocalStorageCache: |
| filter_enabled = request_properties->SupportsImageInlining(); |
| break; |
| case RewriteOptions::kFlushSubresources: |
| filter_enabled = rewrite_driver_->flushed_early();; |
| break; |
| case RewriteOptions::kCachePartialHtml: |
| filter_enabled = rewrite_driver_->flushing_cached_html(); |
| break; |
| case RewriteOptions::kMobilize: |
| filter_enabled = |
| MobilizeRewriteFilter::IsApplicableFor(rewrite_driver_); |
| break; |
| default: |
| break; |
| } |
| if (filter_enabled) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| } // namespace net_instaweb |