Commit 9a107b93 authored by Manish Jethani's avatar Manish Jethani Committed by Commit Bot

Inject and remove style sheets by key

This is the first in a series of patches to implement tabs.removeCSS

A style sheet injected with tabs.insertCSS will have an internal
autogenerated "key" that will be passed to StyleEngine. In the case of
files, this will likely be just the fully qualified name of the file,
whereas in the case of code it could be the code string itself or a hash
digest of the code string. In either case, a call to tabs.removeCSS with
the same options will deterministically generate the same internal key,
thus enabling the removal of a previously injected style sheet without
the explicit use of IDs and such.

This patch lays the groundwork in StyleEngine that will enable us to
implement behavior similar to that observed in Firefox 57.0.

Changes:

 1.  WebStyleSheetId is now WebStyleSheetKey (WebString)
 2.  WebDocument::InsertStyleSheet now accepts an optional key as a
     parameter
 3.  StyleEngine::InjectSheet and StyleEngine::RemoveInjectedSheet now
     take StyleSheetKey (AtomicString) instead of WebStyleSheetId
 4.  Both WebDocument::RemoveInsertedStyleSheet and
     StyleEngine::RemoveInjectedSheet now take the CSS origin as a
     parameter
 5.  StyleEngine::RemoveInjectedSheet now removes only the last style
     sheet injected with the given key and only from the specified
     CSS origin

BUG=608854

Change-Id: Ie62bfcb0d8309b18cbf0d2cd119c74908e396767
Reviewed-on: https://chromium-review.googlesource.com/877663Reviewed-by: default avatarIstiaque Ahmed <lazyboy@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarRune Lillesveen <futhark@chromium.org>
Commit-Queue: Manish Jethani <m.jethani@eyeo.com>
Cr-Commit-Position: refs/heads/master@{#537281}
parent de687559
......@@ -409,7 +409,7 @@ void ScriptInjection::InjectCss(std::set<std::string>* injected_stylesheets,
? blink::WebDocument::kUserOrigin
: blink::WebDocument::kAuthorOrigin;
for (const blink::WebString& css : css_sources)
web_frame->GetDocument().InsertStyleSheet(css, blink_css_origin);
web_frame->GetDocument().InsertStyleSheet(css, nullptr, blink_css_origin);
}
} // namespace extensions
......@@ -141,34 +141,36 @@ StyleEngine::StyleSheetsForStyleSheetList(TreeScope& tree_scope) {
return collection.StyleSheetsForStyleSheetList();
}
WebStyleSheetId StyleEngine::InjectSheet(StyleSheetContents* sheet,
WebDocument::CSSOrigin origin) {
if (origin == WebDocument::kUserOrigin) {
injected_user_style_sheets_.push_back(
std::make_pair(++injected_sheets_id_count_,
CSSStyleSheet::Create(sheet, *document_)));
void StyleEngine::InjectSheet(const StyleSheetKey& key,
StyleSheetContents* sheet,
WebDocument::CSSOrigin origin) {
HeapVector<std::pair<StyleSheetKey, TraceWrapperMember<CSSStyleSheet>>>&
injected_style_sheets = origin == WebDocument::kUserOrigin
? injected_user_style_sheets_
: injected_author_style_sheets_;
injected_style_sheets.push_back(
std::make_pair(key, CSSStyleSheet::Create(sheet, *document_)));
if (origin == WebDocument::kUserOrigin)
MarkUserStyleDirty();
} else {
injected_author_style_sheets_.push_back(
std::make_pair(++injected_sheets_id_count_,
CSSStyleSheet::Create(sheet, *document_)));
else
MarkDocumentDirty();
}
return injected_sheets_id_count_;
}
void StyleEngine::RemoveInjectedSheet(WebStyleSheetId sheet_id) {
for (size_t i = 0; i < injected_user_style_sheets_.size(); ++i) {
if (injected_user_style_sheets_[i].first == sheet_id) {
injected_user_style_sheets_.EraseAt(i);
MarkUserStyleDirty();
}
}
for (size_t i = 0; i < injected_author_style_sheets_.size(); ++i) {
if (injected_author_style_sheets_[i].first == sheet_id) {
injected_author_style_sheets_.EraseAt(i);
MarkDocumentDirty();
void StyleEngine::RemoveInjectedSheet(const StyleSheetKey& key,
WebDocument::CSSOrigin origin) {
HeapVector<std::pair<StyleSheetKey, TraceWrapperMember<CSSStyleSheet>>>&
injected_style_sheets = origin == WebDocument::kUserOrigin
? injected_user_style_sheets_
: injected_author_style_sheets_;
for (auto it = injected_style_sheets.rbegin();
it != injected_style_sheets.rend(); it++) {
if (it->first == key) {
injected_style_sheets.erase(std::next(it).base());
if (origin == WebDocument::kUserOrigin)
MarkUserStyleDirty();
else
MarkDocumentDirty();
break;
}
}
}
......
......@@ -68,6 +68,8 @@ class ViewportStyleResolver;
enum InvalidationScope { kInvalidateCurrentScope, kInvalidateAllScopes };
using StyleSheetKey = AtomicString;
class CORE_EXPORT StyleEngine final
: public GarbageCollectedFinalized<StyleEngine>,
public FontSelectorClient,
......@@ -98,7 +100,7 @@ class CORE_EXPORT StyleEngine final
StyleSheetsForStyleSheetList(TreeScope&);
const HeapVector<
std::pair<WebStyleSheetId, TraceWrapperMember<CSSStyleSheet>>>&
std::pair<StyleSheetKey, TraceWrapperMember<CSSStyleSheet>>>&
InjectedAuthorStyleSheets() const {
return injected_author_style_sheets_;
}
......@@ -119,10 +121,12 @@ class CORE_EXPORT StyleEngine final
void HtmlImportAddedOrRemoved();
void V0ShadowAddedOnV1Document();
WebStyleSheetId InjectSheet(StyleSheetContents*,
WebDocument::CSSOrigin =
WebDocument::kAuthorOrigin);
void RemoveInjectedSheet(WebStyleSheetId);
void InjectSheet(const StyleSheetKey&, StyleSheetContents*,
WebDocument::CSSOrigin =
WebDocument::kAuthorOrigin);
void RemoveInjectedSheet(const StyleSheetKey&,
WebDocument::CSSOrigin =
WebDocument::kAuthorOrigin);
CSSStyleSheet& EnsureInspectorStyleSheet();
RuleSet* WatchedSelectorsRuleSet() {
DCHECK(IsMaster());
......@@ -449,15 +453,13 @@ class CORE_EXPORT StyleEngine final
std::unique_ptr<StyleResolverStats> style_resolver_stats_;
unsigned style_for_element_count_ = 0;
HeapVector<std::pair<WebStyleSheetId, TraceWrapperMember<CSSStyleSheet>>>
HeapVector<std::pair<StyleSheetKey, TraceWrapperMember<CSSStyleSheet>>>
injected_user_style_sheets_;
HeapVector<std::pair<WebStyleSheetId, TraceWrapperMember<CSSStyleSheet>>>
HeapVector<std::pair<StyleSheetKey, TraceWrapperMember<CSSStyleSheet>>>
injected_author_style_sheets_;
ActiveStyleSheetVector active_user_style_sheets_;
WebStyleSheetId injected_sheets_id_count_ = 0;
using KeyframesRuleMap =
HeapHashMap<AtomicString, Member<StyleRuleKeyframes>>;
KeyframesRuleMap keyframes_rule_map_;
......
......@@ -63,6 +63,15 @@
#include "public/web/WebFormElement.h"
#include "v8/include/v8.h"
namespace {
static const blink::WebStyleSheetKey GenerateStyleSheetKey() {
static unsigned counter = 0;
return String::Number(++counter);
}
} // namespace
namespace blink {
WebURL WebDocument::Url() const {
......@@ -183,18 +192,24 @@ WebElement WebDocument::FocusedElement() const {
return WebElement(ConstUnwrap<Document>()->FocusedElement());
}
WebStyleSheetId WebDocument::InsertStyleSheet(const WebString& source_code,
CSSOrigin origin) {
WebStyleSheetKey WebDocument::InsertStyleSheet(const WebString& source_code,
const WebStyleSheetKey* key,
CSSOrigin origin) {
Document* document = Unwrap<Document>();
DCHECK(document);
StyleSheetContents* parsed_sheet =
StyleSheetContents::Create(CSSParserContext::Create(*document));
parsed_sheet->ParseString(source_code);
return document->GetStyleEngine().InjectSheet(parsed_sheet, origin);
const WebStyleSheetKey& injection_key =
key && !key->IsNull() ? *key : GenerateStyleSheetKey();
DCHECK(!injection_key.IsEmpty());
document->GetStyleEngine().InjectSheet(injection_key, parsed_sheet, origin);
return injection_key;
}
void WebDocument::RemoveInsertedStyleSheet(WebStyleSheetId stylesheet_id) {
Unwrap<Document>()->GetStyleEngine().RemoveInjectedSheet(stylesheet_id);
void WebDocument::RemoveInsertedStyleSheet(const WebStyleSheetKey& key,
CSSOrigin origin) {
Unwrap<Document>()->GetStyleEngine().RemoveInjectedSheet(key, origin);
}
void WebDocument::WatchCSSSelectors(const WebVector<WebString>& web_selectors) {
......
......@@ -70,7 +70,7 @@ TEST_F(WebDocumentTest, InsertAndRemoveStyleSheet) {
unsigned start_count = core_doc->GetStyleEngine().StyleForElementCount();
WebStyleSheetId stylesheet_id =
WebStyleSheetKey style_sheet_key =
web_doc.InsertStyleSheet("body { color: green }");
// Check insertStyleSheet did not cause a synchronous style recalc.
......@@ -84,34 +84,34 @@ TEST_F(WebDocumentTest, InsertAndRemoveStyleSheet) {
const ComputedStyle& style_before_insertion =
body_element->ComputedStyleRef();
// Inserted stylesheet not yet applied.
// Inserted style sheet not yet applied.
ASSERT_EQ(Color(0, 0, 0), style_before_insertion.VisitedDependentColor(
GetCSSPropertyColor()));
// Apply inserted stylesheet.
// Apply inserted style sheet.
core_doc->UpdateStyleAndLayoutTree();
const ComputedStyle& style_after_insertion = body_element->ComputedStyleRef();
// Inserted stylesheet applied.
// Inserted style sheet applied.
ASSERT_EQ(Color(0, 128, 0),
style_after_insertion.VisitedDependentColor(GetCSSPropertyColor()));
start_count = core_doc->GetStyleEngine().StyleForElementCount();
// Check RemoveInsertedStyleSheet did not cause a synchronous style recalc.
web_doc.RemoveInsertedStyleSheet(stylesheet_id);
web_doc.RemoveInsertedStyleSheet(style_sheet_key);
element_count =
core_doc->GetStyleEngine().StyleForElementCount() - start_count;
ASSERT_EQ(0U, element_count);
const ComputedStyle& style_before_removing = body_element->ComputedStyleRef();
// Removed stylesheet not yet applied.
// Removed style sheet not yet applied.
ASSERT_EQ(Color(0, 128, 0),
style_before_removing.VisitedDependentColor(GetCSSPropertyColor()));
// Apply removed stylesheet.
// Apply removed style sheet.
core_doc->UpdateStyleAndLayoutTree();
const ComputedStyle& style_after_removing = body_element->ComputedStyleRef();
......
......@@ -55,7 +55,7 @@ class WebString;
class WebURL;
struct WebDistillabilityFeatures;
using WebStyleSheetId = unsigned;
using WebStyleSheetKey = WebString;
// Provides readonly access to some properties of a DOM document.
class WebDocument : public WebNode {
......@@ -110,14 +110,16 @@ class WebDocument : public WebNode {
BLINK_EXPORT WebReferrerPolicy GetReferrerPolicy() const;
BLINK_EXPORT WebString OutgoingReferrer();
// Inserts the given CSS source code as a stylesheet in the document, and
// return its id.
BLINK_EXPORT WebStyleSheetId InsertStyleSheet(const WebString& source_code,
CSSOrigin = kAuthorOrigin);
// Inserts the given CSS source code as a style sheet in the document.
BLINK_EXPORT WebStyleSheetKey InsertStyleSheet(
const WebString& source_code,
const WebStyleSheetKey* = nullptr,
CSSOrigin = kAuthorOrigin);
// Removes the CSS which was previously inserted by a call to
// InsertStyleSheet().
BLINK_EXPORT void RemoveInsertedStyleSheet(WebStyleSheetId);
BLINK_EXPORT void RemoveInsertedStyleSheet(const WebStyleSheetKey&,
CSSOrigin = kAuthorOrigin);
// Arranges to call WebFrameClient::didMatchCSS(frame(), ...) when one of
// the selectors matches or stops matching an element in this document.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment