blob: 6ce8e3babdd85d340197a7b27e3ce72b0980567a [file] [log] [blame]
/*
* Copyright 2015 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: kspoelstra@we-amp.com (Kees Spoelstra)
#include "net/instaweb/rewriter/public/strip_subresource_hints_filter.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/html/html_element.h"
#include "pagespeed/kernel/html/html_name.h"
#include "pagespeed/kernel/http/google_url.h"
#include "net/instaweb/rewriter/public/domain_lawyer.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
namespace net_instaweb {
StripSubresourceHintsFilter::StripSubresourceHintsFilter(RewriteDriver* driver)
: driver_(driver),
delete_element_(nullptr),
remove_script_(false),
remove_style_(false),
remove_image_(false),
remove_any_(false) {
}
StripSubresourceHintsFilter::~StripSubresourceHintsFilter() { }
void StripSubresourceHintsFilter::StartDocument() {
const RewriteOptions *options = driver_->options();
remove_script_ = driver_->can_modify_urls() && !options->js_preserve_urls();
remove_style_ = driver_->can_modify_urls() && !options->css_preserve_urls();
remove_image_ = driver_->can_modify_urls() && !options->image_preserve_urls();
remove_any_ = remove_script_ || remove_style_ || remove_image_;
delete_element_ = nullptr;
// TODO(jefftk): replace can_modify_urls() with can_modify_js_urls(),
// can_modify_css_urls(), and can_modify_image_urls() so that if you, say,
// disable all js-modifying filters then js hints won't be stripped. Right
// now to get this behavior you need to explicitly turn on PreserveJsUrls.
}
bool StripSubresourceHintsFilter::ShouldStrip(HtmlElement* element) {
// Strip:
// <link rel=subresource href=...> regardless
// <link rel=preload as=script href=...> unless preserve scripts
// <link rel=preload as=style href=...> unless preserve styles
// <link rel=preload as=image href=...> unless preserve images
//
// Don't strip other kinds of rel=preload hints, because we don't change
// their urls, so existing ones are still valid.
if (remove_any_ && !delete_element_ &&
element->keyword() == HtmlName::kLink) {
const char* rel_value = element->AttributeValue(HtmlName::kRel);
if (rel_value != nullptr) {
if (StringCaseEqual(rel_value, "subresource")) {
return true;
} else if (StringCaseEqual(rel_value, "preload")) {
const char* as_value = element->AttributeValue(HtmlName::kAs);
if (as_value != nullptr) {
return ((remove_script_ && StringCaseEqual(as_value, "script")) ||
(remove_style_ && StringCaseEqual(as_value, "style")) ||
(remove_image_ && StringCaseEqual(as_value, "image")));
}
}
}
}
return false;
}
void StripSubresourceHintsFilter::StartElement(HtmlElement* element) {
if (ShouldStrip(element)) {
const RewriteOptions *options = driver_->options();
const char *resource_url = element->AttributeValue(HtmlName::kHref);
if (!resource_url) {
// There's either no href attr, or one that we can't decode (utf8 etc).
// One way this could happen is if we have a url-encoded utf8 url in an
// img tag and a utf8 encoded url in the subresource tag. Delete the
// link to be on the safe side.
driver_->DeleteNode(element);
} else {
const GoogleUrl& base_url = driver_->decoded_base_url();
GoogleUrl resolved_resource_url(base_url, resource_url);
if (options->IsAllowed(resolved_resource_url.Spec()) &&
options->domain_lawyer()->IsDomainAuthorized(
base_url, resolved_resource_url)) {
driver_->DeleteNode(element);
}
}
}
}
} // namespace net_instaweb