blob: 2002b8168bf9fa61af40e64be35e1e68091daafb [file] [log] [blame]
/*
* Copyright 2013 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: jkarlin@google.com (Josh Karlin)
#include "net/instaweb/rewriter/public/fake_filter.h"
#include <memory>
#include "net/instaweb/rewriter/cached_result.pb.h"
#include "net/instaweb/rewriter/public/image_url_encoder.h"
#include "net/instaweb/rewriter/public/resource.h"
#include "net/instaweb/rewriter/public/resource_slot.h"
#include "net/instaweb/rewriter/public/resource_tag_scanner.h"
#include "net/instaweb/rewriter/public/rewrite_context.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_result.h"
#include "net/instaweb/rewriter/public/server_context.h"
#include "pagespeed/kernel/base/function.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/timer.h"
#include "pagespeed/kernel/html/html_element.h"
#include "pagespeed/kernel/http/content_type.h"
#include "pagespeed/kernel/thread/scheduler.h"
namespace net_instaweb {
FakeFilter::Context::~Context() {}
void FakeFilter::Context::RewriteSingle(const ResourcePtr& input,
const OutputResourcePtr& output) {
if (filter_->exceed_deadline()) {
// Wake up 1us past the deadline.
int64 wakeup_us = Driver()->scheduler()->timer()->NowUs() +
(Timer::kMsUs * GetRewriteDeadlineAlarmMs() + 1);
Function* closure =
MakeFunction(this, &Context::DoRewriteSingle, input, output);
Driver()->scheduler()->AddAlarmAtUs(wakeup_us, closure);
} else {
DoRewriteSingle(input, output);
}
}
void FakeFilter::Context::DoRewriteSingle(const ResourcePtr input,
OutputResourcePtr output) {
RewriteResult result = kRewriteFailed;
GoogleString rewritten;
if (filter_->enabled()) {
// TODO(jkarlin): Writing to the filter from a context is not thread
// safe.
filter_->IncRewrites();
StrAppend(&rewritten, input->ExtractUncompressedContents(), ":",
filter_->id());
// Set the output type here to make sure that the CachedResult url
// field has the correct extension for the type.
const ContentType* output_type = &kContentTypeText;
if (filter_->output_content_type() != NULL) {
output_type = filter_->output_content_type();
} else if (input->type() != NULL) {
output_type = input->type();
}
ResourceVector rv = ResourceVector(1, input);
if (Driver()->Write(rv, rewritten, output_type, input->charset(),
output.get())) {
result = kRewriteOk;
}
}
RewriteDone(result, 0);
}
GoogleString FakeFilter::Context::UserAgentCacheKey(
const ResourceContext* resource_context) const {
if (resource_context != NULL) {
return ImageUrlEncoder::CacheKeyFromResourceContext(*resource_context);
}
return "";
}
FakeFilter::~FakeFilter() {}
void FakeFilter::StartElementImpl(HtmlElement* element) {
resource_tag_scanner::UrlCategoryVector attributes;
resource_tag_scanner::ScanElement(element, rewrite_options(), &attributes);
for (int i = 0, n = attributes.size(); i < n; ++i) {
if (attributes[i].category == category_) {
ResourcePtr input_resource(CreateInputResourceOrInsertDebugComment(
attributes[i].url->DecodedValueOrNull(), element));
if (input_resource.get() == NULL) {
return;
}
ResourceSlotPtr slot(
driver()->GetSlot(input_resource, element, attributes[i].url));
RewriteContext* context = MakeRewriteContext();
context->AddSlot(slot);
driver()->InitiateRewrite(context);
}
}
}
RewriteContext* FakeFilter::MakeNestedRewriteContext(
RewriteContext* parent, const ResourceSlotPtr& slot) {
ResourceContext* resource_context = new ResourceContext;
if (parent != NULL && parent->resource_context() != NULL) {
resource_context->CopyFrom(*parent->resource_context());
}
RewriteContext* context =
MakeFakeContext(NULL, parent, resource_context);
context->AddSlot(slot);
return context;
}
void FakeFilter::ClearStats() {
num_rewrites_ = 0;
num_calls_to_encode_user_agent_ = 0;
}
void FakeFilter::EncodeUserAgentIntoResourceContext(
ResourceContext* context) const {
ImageUrlEncoder::SetWebpAndMobileUserAgent(*driver(), context);
++num_calls_to_encode_user_agent_;
}
} // namespace net_instaweb