Correctly re-collect active style for html imports.

- Need to re-collect active stylesheets when inserting already cached
  import documents.

- Missing markDocumentDirty() when inserting import documents.

- Added test for missing coverage of the need for marking for re-
  collection from HTMLImportChild::ownerInserted().

The fact that we need to recollect sheets in the document scope and
recalculate style for the whole document is not a perf regression, this
is how it used to be before considering the async stylesheet update
with ruleset invalidations, but ideally we would like to do better.
It's unlikely a common use case as html imports are typically loaded in
head as script and rendering blocking.

R=meade@chromium.org
BUG=567021

Review-Url: https://codereview.chromium.org/2551473002
Cr-Commit-Position: refs/heads/master@{#436238}
diff --git a/third_party/WebKit/LayoutTests/fast/html/imports/import-add-child-to-change-order-of-dup-css.html b/third_party/WebKit/LayoutTests/fast/html/imports/import-add-child-to-change-order-of-dup-css.html
new file mode 100644
index 0000000..585bc24
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/html/imports/import-add-child-to-change-order-of-dup-css.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<link rel="import" href="resources/bye.html"></link>
+<style>.target { color: green }</style>
+<link rel="import" href="resources/style-red.html"></link>
+<div class="target">This text should be green.</div>
+<script>
+    var importDoc = document.querySelectorAll("link")[0].import;
+    var newLink = importDoc.createElement("link");
+    newLink.setAttribute("rel", "import");
+    newLink.setAttribute("href", "style-red.html");
+    var targetElement = document.querySelector(".target");
+
+    test(() => {
+        assert_equals(getComputedStyle(targetElement).color, "rgb(255, 0, 0)");
+    }, ".target should initially be red");
+
+    importDoc.head.appendChild(newLink);
+
+    test(() => {
+        assert_equals(getComputedStyle(targetElement).color, "rgb(0, 128, 0)");
+    }, ".target should be green after style-red.html is inserted as an import child before the inline green style.");
+</script>
diff --git a/third_party/WebKit/Source/core/dom/StyleEngine.cpp b/third_party/WebKit/Source/core/dom/StyleEngine.cpp
index fb1be1e..21d427e9 100644
--- a/third_party/WebKit/Source/core/dom/StyleEngine.cpp
+++ b/third_party/WebKit/Source/core/dom/StyleEngine.cpp
@@ -1050,9 +1050,13 @@
     m_viewportResolver->setNeedsCollectRules();
 }
 
-void StyleEngine::importRemoved() {
+void StyleEngine::htmlImportAddedOrRemoved() {
   if (document().importLoader()) {
-    document().importsController()->master()->styleEngine().importRemoved();
+    document()
+        .importsController()
+        ->master()
+        ->styleEngine()
+        .htmlImportAddedOrRemoved();
     return;
   }
 
@@ -1061,11 +1065,14 @@
   // comparison of active stylesheets is not able to figure out that the order
   // of the stylesheets have changed after insertion.
   //
+  // This is also the case when we import the same document twice where the
+  // last inserted document is inserted before the first one in dom order where
+  // the last would take precedence.
+  //
   // Fall back to re-add all sheets to the scoped resolver and recalculate style
-  // for the whole document if we remove an import in case it is re-inserted
-  // into the document. The assumption is that removing html imports is very
-  // rare.
+  // for the whole document when we remove or insert an import document.
   if (ScopedStyleResolver* resolver = document().scopedStyleResolver()) {
+    markDocumentDirty();
     resolver->setNeedsAppendAllSheets();
     document().setNeedsStyleRecalc(
         SubtreeStyleChange, StyleChangeReasonForTracing::create(
diff --git a/third_party/WebKit/Source/core/dom/StyleEngine.h b/third_party/WebKit/Source/core/dom/StyleEngine.h
index 3e2352e..008236f 100644
--- a/third_party/WebKit/Source/core/dom/StyleEngine.h
+++ b/third_party/WebKit/Source/core/dom/StyleEngine.h
@@ -111,7 +111,7 @@
   void watchedSelectorsChanged();
   void initialViewportChanged();
   void viewportRulesChanged();
-  void importRemoved();
+  void htmlImportAddedOrRemoved();
 
   void injectAuthorSheet(StyleSheetContents* authorSheet);
   CSSStyleSheet& ensureInspectorStyleSheet();
diff --git a/third_party/WebKit/Source/core/html/imports/HTMLImportChild.cpp b/third_party/WebKit/Source/core/html/imports/HTMLImportChild.cpp
index 7b045d5..8718ce5 100644
--- a/third_party/WebKit/Source/core/html/imports/HTMLImportChild.cpp
+++ b/third_party/WebKit/Source/core/html/imports/HTMLImportChild.cpp
@@ -54,7 +54,10 @@
 void HTMLImportChild::ownerInserted() {
   if (!m_loader->isDone())
     return;
-  root()->document()->styleEngine().resolverChanged(FullStyleUpdate);
+  document()->styleEngine().htmlImportAddedOrRemoved();
+  // TODO(rune@opera.com): resolverChanged() can be removed once stylesheet
+  // updates are async. https://crbug.com/567021
+  root()->document()->styleEngine().resolverChanged(AnalyzedStyleUpdate);
 }
 
 void HTMLImportChild::didShareLoader() {
diff --git a/third_party/WebKit/Source/core/html/imports/LinkImport.cpp b/third_party/WebKit/Source/core/html/imports/LinkImport.cpp
index f1de54b..1386ff0 100644
--- a/third_party/WebKit/Source/core/html/imports/LinkImport.cpp
+++ b/third_party/WebKit/Source/core/html/imports/LinkImport.cpp
@@ -120,7 +120,7 @@
 
 void LinkImport::ownerRemoved() {
   if (m_owner)
-    m_owner->document().styleEngine().importRemoved();
+    m_owner->document().styleEngine().htmlImportAddedOrRemoved();
 }
 
 DEFINE_TRACE(LinkImport) {