blob: acfcb464ec4aca1bb39eecc4fc7a3ecb25266cb2 [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/domain_lawyer.h"
#include "net/instaweb/rewriter/public/rewrite_test_base.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/mock_message_handler.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/html/empty_html_filter.h"
namespace {
const char kHtmlDomain[] = "http://test.com/";
const char kOtherDomain[] = "http://other.test.com/";
const char kFrom1Domain[] = "http://from1.test.com/";
const char kFrom2Domain[] = "http://from2.test.com/";
const char kTo1Domain[] = "http://to1.test.com/";
const char kTo2Domain[] = "http://to2.test.com/";
const char kTo2ADomain[] = "http://to2a.test.com/";
const char kTo2BDomain[] = "http://to2b.test.com/";
} // namespace
namespace net_instaweb {
class CanModifyUrlsFilter:public EmptyHtmlFilter {
public:
CanModifyUrlsFilter():
EmptyHtmlFilter(),
can_modify_urls_(false) {
}
void set_can_modify_urls(bool value) { can_modify_urls_ = value; }
virtual bool CanModifyUrls() { return can_modify_urls_; }
virtual const char* Name() const { return "CMURLS"; }
protected:
bool can_modify_urls_;
};
class StripSubresourceHintsFilterTestBase : public RewriteTestBase {
protected:
virtual void SetUp() {
RewriteTestBase::SetUp();
options()->Disallow("*dontdropme*");
DomainLawyer* lawyer = options()->WriteableDomainLawyer();
lawyer->AddRewriteDomainMapping(kTo1Domain, kFrom1Domain,
&message_handler_);
lawyer->AddRewriteDomainMapping(kTo2Domain, kFrom2Domain,
&message_handler_);
lawyer->AddShard(kTo2Domain, StrCat(kTo2ADomain, ",", kTo2BDomain),
&message_handler_);
can_modify_urls_filter_.reset(new CanModifyUrlsFilter());
rewrite_driver()->AddFilter(can_modify_urls_filter_.get());
CustomSetup();
rewrite_driver()->AddFilters();
}
void ValidateStripSubresourceHint(const char *source, const char *rewritten) {
can_modify_urls_filter_->set_can_modify_urls(true);
ValidateExpected("validaterewrite_can_modify_urls_true", source, rewritten);
can_modify_urls_filter_->set_can_modify_urls(false);
ValidateExpected("validaterewrite_can_modify_urls_false", source, source);
}
virtual void CustomSetup() { }
scoped_ptr<CanModifyUrlsFilter> can_modify_urls_filter_;
};
class StripSubresourceHintsFilterTest :
public StripSubresourceHintsFilterTestBase {
};
class StripSubresourceHintsFilterTestPreserveStyle :
public StripSubresourceHintsFilterTestBase {
protected:
virtual void CustomSetup() {
options()->set_css_preserve_urls(true);
options()->set_js_preserve_urls(false);
options()->set_image_preserve_urls(false);
}
};
class StripSubresourceHintsFilterTestPreserveScript :
public StripSubresourceHintsFilterTestBase {
protected:
virtual void CustomSetup() {
options()->set_css_preserve_urls(false);
options()->set_js_preserve_urls(true);
options()->set_image_preserve_urls(false);
}
};
class StripSubresourceHintsFilterTestPreserveImage :
public StripSubresourceHintsFilterTestBase {
protected:
virtual void CustomSetup() {
options()->set_css_preserve_urls(false);
options()->set_js_preserve_urls(false);
options()->set_image_preserve_urls(true);
}
};
class StripSubresourceHintsFilterTestFullPreserve : public
StripSubresourceHintsFilterTestBase {
protected:
virtual void CustomSetup() {
options()->set_css_preserve_urls(true);
options()->set_js_preserve_urls(true);
options()->set_image_preserve_urls(true);
}
};
class StripSubresourceHintsFilterTestDisabled :
public StripSubresourceHintsFilterTestBase {
protected:
virtual void CustomSetup() {
options()->set_preserve_subresource_hints(true);
}
};
class StripSubresourceHintsFilterTestRewriteLevelPassthrough :
public StripSubresourceHintsFilterTestBase {
protected:
virtual void CustomSetup() {
options()->SetRewriteLevel(RewriteOptions::kPassThrough);
}
};
class StripSubresourceHintsFilterTestRewriteLevelCoreFilters :
public StripSubresourceHintsFilterTestBase {
protected:
virtual void CustomSetup() {
options()->SetRewriteLevel(RewriteOptions::kCoreFilters);
}
};
TEST_F(StripSubresourceHintsFilterTest, PreserveSubResourceHintsIsFalse) {
EXPECT_FALSE(options()->preserve_subresource_hints());
}
TEST_F(StripSubresourceHintsFilterTest, SingleResourceNoLink) {
const char *source =
"<head><link rel=\"subresource\"/></head>"
"<body><img src=\"1.jpg\"/></body>";
const char *rewritten =
"<head></head>"
"<body><img src=\"1.jpg\"/></body>";
ValidateStripSubresourceHint(source, rewritten);
}
TEST_F(StripSubresourceHintsFilterTest, SingleResourceValidLink) {
const char *source =
"<head><link rel=\"subresource\" href=\"/test.gif\"/></head>"
"<body><img src=\"1.jpg\"/></body>";
const char *rewritten =
"<head></head>"
"<body><img src=\"1.jpg\"/></body>";
ValidateStripSubresourceHint(source, rewritten);
}
TEST_F(StripSubresourceHintsFilterTest, SingleResourceValidPreloadLink) {
const char *source =
"<head><link rel=\"preload\" href=\"/test.gif\" as=\"image\"/></head>"
"<body><img src=\"1.jpg\"/></body>";
const char *rewritten =
"<head></head>"
"<body><img src=\"1.jpg\"/></body>";
ValidateStripSubresourceHint(source, rewritten);
}
TEST_F(StripSubresourceHintsFilterTest, SingleResourceExternalLink) {
const char *source =
"<head>"
"<link rel=\"subresource\" href=\"http://www.example.com/test.gif\"/>"
"</head>"
"<body><img src=\"1.jpg\"/></body>";
ValidateStripSubresourceHint(source, source);
}
TEST_F(StripSubresourceHintsFilterTest, MultiResourceMixedLinks) {
const char *source =
"<head>"
"<link rel=\"subresource\" href=\"/test.gif\"/>"
"<link rel=\"subresource\" href=\"http://www.example.com/test.gif\"/>"
"</head>"
"<body><img src=\"1.jpg\"/></body>";
const char *rewritten =
"<head>"
"<link rel=\"subresource\" href=\"http://www.example.com/test.gif\"/>"
"</head>"
"<body><img src=\"1.jpg\"/></body>";
ValidateStripSubresourceHint(source, rewritten);
}
TEST_F(StripSubresourceHintsFilterTest, SingleResourceRewriteDomain) {
const char *source =
"<head><link rel=\"subresource\" href=\"http://from1.test.com/test.gif\"/>"
"</head>"
"<body><img src=\"1.jpg\"/></body>";
const char *rewritten =
"<head></head>"
"<body><img src=\"1.jpg\"/></body>";
ValidateStripSubresourceHint(source, rewritten);
}
TEST_F(StripSubresourceHintsFilterTest, SingleResourceDisallow) {
const char *source =
"<head><link rel=\"subresource\" href=\"/dontdropme/test.gif\"/>"
"</head>"
"<body><img src=\"1.jpg\"/></body>";
const char *rewritten =
"<head><link rel=\"subresource\" href=\"/dontdropme/test.gif\"/>"
"</head>"
"<body><img src=\"1.jpg\"/></body>";
ValidateStripSubresourceHint(source, rewritten);
}
// Even if you turn on preserve images, we still strip all rel=subresource hints
// because we don't know which ones are images.
TEST_F(StripSubresourceHintsFilterTestPreserveImage,
MultiSubresourcePreserveImages) {
const char *source =
"<head>"
"<link rel=\"subresource\" href=\"/dontdropme.gif\"/>"
"<link rel=\"subresource\" href=\"/test.gif\"/>"
"<link rel=\"subresource\" href=\"http://from1.test.com/test.gif\"/>"
"<link rel=\"subresource\" href=\"http://www.example.com/test.gif\"/>"
"</head>"
"<body><img src=\"1.jpg\"/></body>";
const char *rewritten =
"<head>"
"<link rel=\"subresource\" href=\"/dontdropme.gif\"/>"
"<link rel=\"subresource\" href=\"http://www.example.com/test.gif\"/>"
"</head>"
"<body><img src=\"1.jpg\"/></body>";
ValidateStripSubresourceHint(source, rewritten);
}
TEST_F(StripSubresourceHintsFilterTestFullPreserve,
MultiResourcePreserveAll) {
const char *source =
"<head>"
"<link rel=\"subresource\" href=\"/dontdropme.gif\"/>"
"<link rel=\"subresource\" href=\"/test.gif\"/>"
"<link rel=\"subresource\" href=\"http://from1.test.com/test.gif\"/>"
"<link rel=\"subresource\" href=\"http://www.example.com/test.gif\"/>"
"</head>"
"<body><img src=\"1.jpg\"/></body>";
const char *rewritten =
"<head>"
"<link rel=\"subresource\" href=\"/dontdropme.gif\"/>"
"<link rel=\"subresource\" href=\"/test.gif\"/>"
"<link rel=\"subresource\" href=\"http://from1.test.com/test.gif\"/>"
"<link rel=\"subresource\" href=\"http://www.example.com/test.gif\"/>"
"</head>"
"<body><img src=\"1.jpg\"/></body>";
ValidateStripSubresourceHint(source, rewritten);
}
// With rel=preload, if you have set preserve for a type we don't strip it.
TEST_F(StripSubresourceHintsFilterTestPreserveImage, ImagesPreserved) {
const char* source =
"<link rel=preload as=image href=a.jpg>"
"<link rel=preload as=script href=a.js>"
"<link rel=preload as=style href=a.css>";
const char* rewritten =
"<link rel=preload as=image href=a.jpg>";
ValidateStripSubresourceHint(source, rewritten);
}
TEST_F(StripSubresourceHintsFilterTestPreserveScript, ScriptsPreserved) {
const char* source =
"<link rel=preload as=image href=a.jpg>"
"<link rel=preload as=script href=a.js>"
"<link rel=preload as=style href=a.css>";
const char* rewritten =
"<link rel=preload as=script href=a.js>";
ValidateStripSubresourceHint(source, rewritten);
}
TEST_F(StripSubresourceHintsFilterTestPreserveStyle, StylesPreserved) {
const char* source =
"<link rel=preload as=image href=a.jpg>"
"<link rel=preload as=script href=a.js>"
"<link rel=preload as=style href=a.css>";
const char* rewritten =
"<link rel=preload as=style href=a.css>";
ValidateStripSubresourceHint(source, rewritten);
}
// With rel=preload we don't strip unknown types.
TEST_F(StripSubresourceHintsFilterTest, DontStripUnknownTypes) {
const char* source = "<link rel=preload as=font href=a.woff>";
ValidateStripSubresourceHint(source, source);
}
TEST_F(StripSubresourceHintsFilterTestDisabled,
PreserveSubResourceHintsIsTrue) {
can_modify_urls_filter_->set_can_modify_urls(true);
EXPECT_TRUE(options()->preserve_subresource_hints());
}
TEST_F(StripSubresourceHintsFilterTestDisabled,
MultiResourcePreserveAll) {
can_modify_urls_filter_->set_can_modify_urls(true);
const char *source =
"<head>"
"<link rel=\"subresource\" href=\"/dontdropme.gif\"/>"
"<link rel=\"subresource\" href=\"/test.gif\"/>"
"<link rel=\"subresource\" href=\"http://from1.test.com/test.gif\"/>"
"<link rel=\"subresource\" href=\"http://www.example.com/test.gif\"/>"
"</head>"
"<body><img src=\"1.jpg\"/></body>";
ValidateStripSubresourceHint(source, source);
}
TEST_F(StripSubresourceHintsFilterTestRewriteLevelPassthrough,
MultiResource) {
const char *source =
"<head>"
"<link rel=\"subresource\" href=\"/dontdropme.gif\"/>"
"<link rel=\"subresource\" href=\"/test.gif\"/>"
"<link rel=\"subresource\" href=\"http://from1.test.com/test.gif\"/>"
"<link rel=\"subresource\" href=\"http://www.example.com/test.gif\"/>"
"</head>"
"<body></body>";
const char *rewritten =
"<head>"
"<link rel=\"subresource\" href=\"/dontdropme.gif\"/>"
"<link rel=\"subresource\" href=\"/test.gif\"/>"
"<link rel=\"subresource\" href=\"http://from1.test.com/test.gif\"/>"
"<link rel=\"subresource\" href=\"http://www.example.com/test.gif\"/>"
"</head>"
"<body></body>";
ValidateExpected("multi_resource", source, rewritten);
}
TEST_F(StripSubresourceHintsFilterTestRewriteLevelCoreFilters,
MultiResource) {
const char *source =
"<head>"
"<link rel=\"subresource\" href=\"/dontdropme.gif\"/>"
"<link rel=\"subresource\" href=\"/test.gif\"/>"
"<link rel=\"subresource\" href=\"http://from1.test.com/test.gif\"/>"
"<link rel=\"subresource\" href=\"http://www.example.com/test.gif\"/>"
"</head>"
"<body></body>";
const char *rewritten =
"<head>"
"<link rel=\"subresource\" href=\"/dontdropme.gif\"/>"
"<link rel=\"subresource\" href=\"http://www.example.com/test.gif\"/>"
"</head>"
"<body></body>";
ValidateExpected("multi_resource", source, rewritten);
}
} // namespace net_instaweb