[LargestContentfulPaint] Add attributes and checks

This CL adds checks so that we do not expose rendering timestamp of
images which do not pass the Timing Allow Origin check. It also adds
attributes found in:
https://wicg.github.io/largest-contentful-paint/#sec-performance-largest-contentful-paint-candidate

The ImagePaintTimingDetector did not plumb the ImageResourceContent to
the ImageRecord, so this is fixed to allow LCP Calculator to make use of
it.

Bug: 965505
Change-Id: I019658dc6d130c8cea336f1ca70de6a32beebbb0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1674588
Reviewed-by: Chris Harrelson <chrishtr@chromium.org>
Commit-Queue: Nicolás Peña Moreno <npm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#674085}
diff --git a/largest-contentful-paint/cross-origin-image.sub.html b/largest-contentful-paint/cross-origin-image.sub.html
new file mode 100644
index 0000000..3716f93
--- /dev/null
+++ b/largest-contentful-paint/cross-origin-image.sub.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Largest Contentful Paint: observe cross-origin images but without startTime.</title>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+  async_test(function (t) {
+    if (!window.LargestContentfulPaint) {
+      assert_unreached("LargestContentfulPaint is not implemented");
+    }
+    const observer = new PerformanceObserver(
+      t.step_func_done(function(entryList) {
+        assert_equals(entryList.getEntries().length, 1);
+        const entry = entryList.getEntries()[0];
+        assert_equals(entry.entryType, 'largestContentfulPaint');
+        assert_equals(entry.startTime, 0, 'The startTime value should be 0 for a cross origin image.');
+        assert_equals(entry.duration, 0);
+        // blue.png is 133 x 106.
+        assert_equals(entry.size, 14098);
+        assert_equals(entry.id, 'image_id');
+        const pathname = 'http://{{domains[www]}}:{{ports[http][1]}}/images/blue.png';
+        assert_equals(entry.url, pathname);
+        assert_equals(entry.responseEnd,
+            performance.getEntriesByName(pathname, 'resource')[0].responseEnd);
+        assert_equals(entry.element, document.getElementById('image_id'));
+      })
+    );
+    observer.observe({type: 'largestContentfulPaint', buffered: true});
+  }, 'Cross-origin image is observable, with startTime equal to 0.');
+</script>
+
+<img src='http://{{domains[www]}}:{{ports[http][1]}}/images/blue.png' id='image_id'/>
+</body>
diff --git a/largest-contentful-paint/observe-image.html b/largest-contentful-paint/observe-image.html
index 43cdfab..8adf215 100644
--- a/largest-contentful-paint/observe-image.html
+++ b/largest-contentful-paint/observe-image.html
@@ -22,11 +22,19 @@
         assert_equals(entry.duration, 0);
         // blue.png is 133 x 106.
         assert_equals(entry.size, 14098);
+        assert_equals(entry.id, 'image_id');
+        // 25 is the length of "largest-contentful-paint/".
+        const index = window.location.href.lastIndexOf('/') - 25;
+        const pathname = window.location.href.substring(0, index) + '/images/blue.png';
+        assert_equals(entry.url, pathname);
+        assert_equals(entry.responseEnd,
+            performance.getEntriesByName(pathname, 'resource')[0].responseEnd);
+        assert_equals(entry.element, document.getElementById('image_id'));
       })
     );
     observer.observe({type: 'largestContentfulPaint', buffered: true});
-  }, 'Element with elementtiming attribute is observable.');
+  }, 'Same-origin image is observable.');
 </script>
 
-<img src='/images/blue.png'/>
+<img src='/images/blue.png' id='image_id'/>
 </body>
diff --git a/largest-contentful-paint/observe-text.html b/largest-contentful-paint/observe-text.html
index 77ed06e..a9a0d75 100644
--- a/largest-contentful-paint/observe-text.html
+++ b/largest-contentful-paint/observe-text.html
@@ -27,6 +27,10 @@
         // Width of at least 100 px.
         // TODO: find a good way to bound text width.
         assert_greater_than_equal(entry.size, 1200);
+        assert_equals(entry.responseEnd, 0);
+        assert_equals(entry.id, 'my_text');
+        assert_equals(entry.url, '');
+        assert_equals(entry.element, document.getElementById('my_text'));
       })
     );
     observer.observe({type: 'largestContentfulPaint', buffered: true});
@@ -34,5 +38,5 @@
   }, 'Element with elementtiming attribute is observable.');
 </script>
 
-<p>This is important text! :)</p>
+<p id='my_text'>This is important text! :)</p>
 </body>