blob: 40cf99a85bd0154809b711eae076d978a759b2b3 [file] [log] [blame]
/*
* (C) 1999-2003 Lars Knoll (knoll@kde.org)
* (C) 2002-2003 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2002, 2005, 2006, 2008, 2009, 2010, 2012 Apple Inc. All rights
* reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "core/css/StyleRuleImport.h"
#include "core/css/StyleSheetContents.h"
#include "core/dom/Document.h"
#include "core/loader/resource/CSSStyleSheetResource.h"
#include "platform/loader/fetch/FetchParameters.h"
#include "platform/loader/fetch/ResourceFetcher.h"
#include "platform/loader/fetch/ResourceLoaderOptions.h"
#include "platform/loader/fetch/fetch_initiator_type_names.h"
namespace blink {
StyleRuleImport* StyleRuleImport::Create(const String& href,
scoped_refptr<MediaQuerySet> media) {
return new StyleRuleImport(href, media);
}
StyleRuleImport::StyleRuleImport(const String& href,
scoped_refptr<MediaQuerySet> media)
: StyleRuleBase(kImport),
parent_style_sheet_(nullptr),
style_sheet_client_(new ImportedStyleSheetClient(this)),
str_href_(href),
media_queries_(media),
loading_(false) {
if (!media_queries_)
media_queries_ = MediaQuerySet::Create(String());
}
StyleRuleImport::~StyleRuleImport() = default;
void StyleRuleImport::Dispose() {
style_sheet_client_->Dispose();
}
void StyleRuleImport::TraceAfterDispatch(blink::Visitor* visitor) {
visitor->Trace(style_sheet_client_);
visitor->Trace(parent_style_sheet_);
visitor->Trace(style_sheet_);
StyleRuleBase::TraceAfterDispatch(visitor);
}
void StyleRuleImport::NotifyFinished(Resource* resource) {
if (style_sheet_)
style_sheet_->ClearOwnerRule();
CSSStyleSheetResource* cached_style_sheet = ToCSSStyleSheetResource(resource);
Document* document = nullptr;
// Fallback to an insecure context parser if we don't have a parent style
// sheet.
const CSSParserContext* context =
StrictCSSParserContext(SecureContextMode::kInsecureContext);
if (parent_style_sheet_) {
document = parent_style_sheet_->SingleOwnerDocument();
context = parent_style_sheet_->ParserContext();
}
context =
CSSParserContext::Create(context, cached_style_sheet->GetResponse().Url(),
cached_style_sheet->GetReferrerPolicy(),
cached_style_sheet->Encoding(), document);
style_sheet_ =
StyleSheetContents::Create(this, cached_style_sheet->Url(), context);
style_sheet_->ParseAuthorStyleSheet(
cached_style_sheet, document ? document->GetSecurityOrigin() : nullptr);
loading_ = false;
if (parent_style_sheet_) {
parent_style_sheet_->NotifyLoadedSheet(cached_style_sheet);
parent_style_sheet_->CheckLoaded();
}
}
bool StyleRuleImport::IsLoading() const {
return loading_ || (style_sheet_ && style_sheet_->IsLoading());
}
void StyleRuleImport::RequestStyleSheet() {
if (!parent_style_sheet_)
return;
Document* document = parent_style_sheet_->SingleOwnerDocument();
if (!document)
return;
ResourceFetcher* fetcher = document->Fetcher();
if (!fetcher)
return;
KURL abs_url;
if (!parent_style_sheet_->BaseURL().IsNull()) {
// use parent styleheet's URL as the base URL
abs_url = KURL(parent_style_sheet_->BaseURL(), str_href_);
} else {
abs_url = document->CompleteURL(str_href_);
}
// Check for a cycle in our import chain. If we encounter a stylesheet
// in our parent chain with the same URL, then just bail.
StyleSheetContents* root_sheet = parent_style_sheet_;
for (StyleSheetContents* sheet = parent_style_sheet_; sheet;
sheet = sheet->ParentStyleSheet()) {
if (EqualIgnoringFragmentIdentifier(abs_url, sheet->BaseURL()) ||
EqualIgnoringFragmentIdentifier(
abs_url, document->CompleteURL(sheet->OriginalURL())))
return;
root_sheet = sheet;
}
ResourceLoaderOptions options;
options.initiator_info.name = FetchInitiatorTypeNames::css;
FetchParameters params(ResourceRequest(abs_url), options);
params.SetCharset(parent_style_sheet_->Charset());
loading_ = true;
DCHECK(!style_sheet_client_->GetResource());
if (!CSSStyleSheetResource::Fetch(params, fetcher, style_sheet_client_)) {
loading_ = false;
} else if (loading_) {
// if the import rule is issued dynamically, the sheet may be
// removed from the pending sheet count, so let the doc know
// the sheet being imported is pending.
if (parent_style_sheet_ && parent_style_sheet_->LoadCompleted() &&
root_sheet == parent_style_sheet_) {
parent_style_sheet_->StartLoadingDynamicSheet();
}
}
}
} // namespace blink