blob: 918805bd73dc171c78d0e8c69189dd533f044844 [file] [log] [blame]
/*
* Copyright 2011 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: morlovich@google.com (Maksim Orlovich)
#include "net/instaweb/rewriter/public/inline_rewrite_context.h"
#include "base/logging.h"
#include "net/instaweb/rewriter/cached_result.pb.h"
#include "net/instaweb/rewriter/public/common_filter.h"
#include "net/instaweb/rewriter/public/output_resource_kind.h"
#include "net/instaweb/rewriter/public/resource.h"
#include "net/instaweb/rewriter/public/resource_slot.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/string_util.h"
#include "pagespeed/kernel/html/html_element.h"
namespace net_instaweb {
InlineRewriteContext::InlineRewriteContext(CommonFilter* filter,
HtmlElement* element,
HtmlElement::Attribute* src)
: RewriteContext(filter->driver(), NULL, NULL),
filter_(filter),
element_(element),
src_(src) {
}
InlineRewriteContext::~InlineRewriteContext() {
}
bool InlineRewriteContext::StartInlining() {
RewriteDriver* driver = filter_->driver();
ResourcePtr input_resource;
const char* url = src_->DecodedValueOrNull();
if (url != NULL) {
bool is_authorized;
input_resource.reset(CreateResource(url, &is_authorized));
if (input_resource.get() != NULL) {
ResourceSlotPtr slot(driver->GetSlot(input_resource, element_, src_));
AddSlot(slot);
driver->InitiateRewrite(this);
return true;
}
if (!is_authorized) {
driver->InsertUnauthorizedDomainDebugComment(url, element_);
}
} else if (driver->DebugMode()) {
driver->InsertDebugComment("Following resource not rewritten because its "
"src attribute cannot be decoded", element_);
}
delete this;
return false;
}
ResourcePtr InlineRewriteContext::CreateResource(const char* url,
bool* is_authorized) {
return filter_->CreateInputResource(url, is_authorized);
}
bool InlineRewriteContext::Partition(OutputPartitions* partitions,
OutputResourceVector* outputs) {
CHECK_EQ(1, num_slots()) << "InlineRewriteContext only handles one slot";
ResourcePtr resource(slot(0)->resource());
// Always create someplace to store stuff, since we may need debug info.
CachedResult* partition = partitions->add_partition();
outputs->push_back(OutputResourcePtr(NULL));
bool ok = false;
GoogleString reason_for_failure;
if (!resource->IsSafeToRewrite(rewrite_uncacheable(), &reason_for_failure)) {
AddRecheckDependency();
} else {
resource->AddInputInfoToPartition(Resource::kOmitInputHash, 0, partition);
if (ShouldInline(resource, &reason_for_failure)) {
StringPiece contents = resource->ExtractUncompressedContents();
contents.CopyToString(partition->mutable_inlined_data());
ok = true;
}
}
if (!ok) {
partition->add_debug_message(reason_for_failure);
}
return true;
}
void InlineRewriteContext::Rewrite(int partition_index,
CachedResult* partition,
const OutputResourcePtr& output_resource) {
CHECK(output_resource.get() == NULL);
CHECK_EQ(0, partition_index);
// Mark slot as needing no further processing. Note that needs to be done
// before calling RewriteDone, as that may cause us to be deleted!
if (output_partition(0)->has_inlined_data()) {
slot(0)->set_disable_further_processing(true);
}
// We signal as rewrite failed, as we do not create an output resource.
RewriteDone(kRewriteFailed, 0);
}
void InlineRewriteContext::Render() {
if (num_output_partitions() == 1 &&
output_partition(0)->has_inlined_data() &&
!slot(0)->should_delete_element()) {
// We've decided to inline, and no one destroyed our element before us.
// Set disable_rendering = true because we will render directly here.
slot(0)->set_disable_rendering(true);
ResourceSlotPtr our_slot = slot(0);
RenderInline(
our_slot->resource(), output_partition(0)->inlined_data(), element_);
}
}
// We never create output resources, so methods related to them are stubbed.
OutputResourceKind InlineRewriteContext::kind() const {
LOG(FATAL);
return kRewrittenResource;
}
} // namespace net_instaweb