| OLD | NEW | 
|    1 // Copyright 2015 The Chromium Authors. All rights reserved. |    1 // Copyright 2015 The Chromium Authors. All rights reserved. | 
|    2 // Use of this source code is governed by a BSD-style license that can be |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" |    5 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" | 
|    6  |    6  | 
|    7 #include <memory> |    7 #include <memory> | 
|    8 #include <vector> |    8 #include <vector> | 
|    9  |    9  | 
|   10 #include "base/macros.h" |   10 #include "base/macros.h" | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
|   37 const char kFilteredCommitUrl[] = "https://whatever.com/ignore-on-commit"; |   37 const char kFilteredCommitUrl[] = "https://whatever.com/ignore-on-commit"; | 
|   38  |   38  | 
|   39 // Simple PageLoadMetricsObserver that copies observed PageLoadTimings into the |   39 // Simple PageLoadMetricsObserver that copies observed PageLoadTimings into the | 
|   40 // provided std::vector, so they can be analyzed by unit tests. |   40 // provided std::vector, so they can be analyzed by unit tests. | 
|   41 class TestPageLoadMetricsObserver |   41 class TestPageLoadMetricsObserver | 
|   42     : public PageLoadMetricsObserver, |   42     : public PageLoadMetricsObserver, | 
|   43       public MetricsWebContentsObserver::TestingObserver { |   43       public MetricsWebContentsObserver::TestingObserver { | 
|   44  public: |   44  public: | 
|   45   TestPageLoadMetricsObserver( |   45   TestPageLoadMetricsObserver( | 
|   46       content::WebContents* web_contents, |   46       content::WebContents* web_contents, | 
|   47       std::vector<PageLoadTiming>* updated_timings, |   47       std::vector<mojom::PageLoadTimingPtr>* updated_timings, | 
|   48       std::vector<PageLoadTiming>* updated_subframe_timings, |   48       std::vector<mojom::PageLoadTimingPtr>* updated_subframe_timings, | 
|   49       std::vector<PageLoadTiming>* complete_timings, |   49       std::vector<mojom::PageLoadTimingPtr>* complete_timings, | 
|   50       std::vector<GURL>* observed_committed_urls) |   50       std::vector<GURL>* observed_committed_urls) | 
|   51       : MetricsWebContentsObserver::TestingObserver(web_contents), |   51       : MetricsWebContentsObserver::TestingObserver(web_contents), | 
|   52         updated_timings_(updated_timings), |   52         updated_timings_(updated_timings), | 
|   53         updated_subframe_timings_(updated_subframe_timings), |   53         updated_subframe_timings_(updated_subframe_timings), | 
|   54         complete_timings_(complete_timings), |   54         complete_timings_(complete_timings), | 
|   55         observed_committed_urls_(observed_committed_urls) {} |   55         observed_committed_urls_(observed_committed_urls) {} | 
|   56  |   56  | 
|   57   ObservePolicy OnStart(content::NavigationHandle* navigation_handle, |   57   ObservePolicy OnStart(content::NavigationHandle* navigation_handle, | 
|   58                const GURL& currently_committed_url, |   58                const GURL& currently_committed_url, | 
|   59                bool started_in_foreground) override { |   59                bool started_in_foreground) override { | 
|   60     observed_committed_urls_->push_back(currently_committed_url); |   60     observed_committed_urls_->push_back(currently_committed_url); | 
|   61     return CONTINUE_OBSERVING; |   61     return CONTINUE_OBSERVING; | 
|   62   } |   62   } | 
|   63  |   63  | 
|   64   void OnTimingUpdate(const PageLoadTiming& timing, |   64   void OnTimingUpdate(const mojom::PageLoadTiming& timing, | 
|   65                       const PageLoadExtraInfo& extra_info) override { |   65                       const PageLoadExtraInfo& extra_info) override { | 
|   66     updated_timings_->push_back(timing); |   66     updated_timings_->push_back(timing.Clone()); | 
|   67   } |   67   } | 
|   68  |   68  | 
|   69   void OnTimingUpdated(bool is_main_frame, |   69   void OnTimingUpdated(bool is_main_frame, | 
|   70                        const PageLoadTiming& timing, |   70                        const mojom::PageLoadTiming& timing, | 
|   71                        const PageLoadMetadata& metadata) override { |   71                        const mojom::PageLoadMetadata& metadata) override { | 
|   72     if (!is_main_frame) { |   72     if (!is_main_frame) { | 
|   73       updated_subframe_timings_->push_back(timing); |   73       updated_subframe_timings_->push_back(timing.Clone()); | 
|   74     } |   74     } | 
|   75   } |   75   } | 
|   76  |   76  | 
|   77   void OnComplete(const PageLoadTiming& timing, |   77   void OnComplete(const mojom::PageLoadTiming& timing, | 
|   78                   const PageLoadExtraInfo& extra_info) override { |   78                   const PageLoadExtraInfo& extra_info) override { | 
|   79     complete_timings_->push_back(timing); |   79     complete_timings_->push_back(timing.Clone()); | 
|   80   } |   80   } | 
|   81  |   81  | 
|   82   ObservePolicy FlushMetricsOnAppEnterBackground( |   82   ObservePolicy FlushMetricsOnAppEnterBackground( | 
|   83       const PageLoadTiming& timing, |   83       const mojom::PageLoadTiming& timing, | 
|   84       const PageLoadExtraInfo& extra_info) override { |   84       const PageLoadExtraInfo& extra_info) override { | 
|   85     return STOP_OBSERVING; |   85     return STOP_OBSERVING; | 
|   86   } |   86   } | 
|   87  |   87  | 
|   88  private: |   88  private: | 
|   89   std::vector<PageLoadTiming>* const updated_timings_; |   89   std::vector<mojom::PageLoadTimingPtr>* const updated_timings_; | 
|   90   std::vector<PageLoadTiming>* const updated_subframe_timings_; |   90   std::vector<mojom::PageLoadTimingPtr>* const updated_subframe_timings_; | 
|   91   std::vector<PageLoadTiming>* const complete_timings_; |   91   std::vector<mojom::PageLoadTimingPtr>* const complete_timings_; | 
|   92   std::vector<GURL>* const observed_committed_urls_; |   92   std::vector<GURL>* const observed_committed_urls_; | 
|   93 }; |   93 }; | 
|   94  |   94  | 
|   95 // Test PageLoadMetricsObserver that stops observing page loads with certain |   95 // Test PageLoadMetricsObserver that stops observing page loads with certain | 
|   96 // substrings in the URL. |   96 // substrings in the URL. | 
|   97 class FilteringPageLoadMetricsObserver : public PageLoadMetricsObserver { |   97 class FilteringPageLoadMetricsObserver : public PageLoadMetricsObserver { | 
|   98  public: |   98  public: | 
|   99   explicit FilteringPageLoadMetricsObserver( |   99   explicit FilteringPageLoadMetricsObserver( | 
|  100       std::vector<GURL>* completed_filtered_urls) |  100       std::vector<GURL>* completed_filtered_urls) | 
|  101       : completed_filtered_urls_(completed_filtered_urls) {} |  101       : completed_filtered_urls_(completed_filtered_urls) {} | 
|  102  |  102  | 
|  103   ObservePolicy OnStart(content::NavigationHandle* handle, |  103   ObservePolicy OnStart(content::NavigationHandle* handle, | 
|  104                         const GURL& currently_committed_url, |  104                         const GURL& currently_committed_url, | 
|  105                         bool started_in_foreground) override { |  105                         bool started_in_foreground) override { | 
|  106     const bool should_ignore = |  106     const bool should_ignore = | 
|  107         handle->GetURL().spec().find("ignore-on-start") != std::string::npos; |  107         handle->GetURL().spec().find("ignore-on-start") != std::string::npos; | 
|  108     return should_ignore ? STOP_OBSERVING : CONTINUE_OBSERVING; |  108     return should_ignore ? STOP_OBSERVING : CONTINUE_OBSERVING; | 
|  109   } |  109   } | 
|  110  |  110  | 
|  111   ObservePolicy OnCommit(content::NavigationHandle* handle) override { |  111   ObservePolicy OnCommit(content::NavigationHandle* handle) override { | 
|  112     const bool should_ignore = |  112     const bool should_ignore = | 
|  113         handle->GetURL().spec().find("ignore-on-commit") != std::string::npos; |  113         handle->GetURL().spec().find("ignore-on-commit") != std::string::npos; | 
|  114     return should_ignore ? STOP_OBSERVING : CONTINUE_OBSERVING; |  114     return should_ignore ? STOP_OBSERVING : CONTINUE_OBSERVING; | 
|  115   } |  115   } | 
|  116  |  116  | 
|  117   void OnComplete(const PageLoadTiming& timing, |  117   void OnComplete(const mojom::PageLoadTiming& timing, | 
|  118                   const PageLoadExtraInfo& extra_info) override { |  118                   const PageLoadExtraInfo& extra_info) override { | 
|  119     completed_filtered_urls_->push_back(extra_info.url); |  119     completed_filtered_urls_->push_back(extra_info.url); | 
|  120   } |  120   } | 
|  121  |  121  | 
|  122  private: |  122  private: | 
|  123   std::vector<GURL>* const completed_filtered_urls_; |  123   std::vector<GURL>* const completed_filtered_urls_; | 
|  124 }; |  124 }; | 
|  125  |  125  | 
|  126 class TestPageLoadMetricsEmbedderInterface |  126 class TestPageLoadMetricsEmbedderInterface | 
|  127     : public PageLoadMetricsEmbedderInterface { |  127     : public PageLoadMetricsEmbedderInterface { | 
|  128  public: |  128  public: | 
|  129   explicit TestPageLoadMetricsEmbedderInterface( |  129   explicit TestPageLoadMetricsEmbedderInterface( | 
|  130       content::WebContents* web_contents) |  130       content::WebContents* web_contents) | 
|  131       : web_contents_(web_contents), is_ntp_(false) {} |  131       : web_contents_(web_contents), is_ntp_(false) {} | 
|  132  |  132  | 
|  133   bool IsNewTabPageUrl(const GURL& url) override { return is_ntp_; } |  133   bool IsNewTabPageUrl(const GURL& url) override { return is_ntp_; } | 
|  134   void set_is_ntp(bool is_ntp) { is_ntp_ = is_ntp; } |  134   void set_is_ntp(bool is_ntp) { is_ntp_ = is_ntp; } | 
|  135   void RegisterObservers(PageLoadTracker* tracker) override { |  135   void RegisterObservers(PageLoadTracker* tracker) override { | 
|  136     tracker->AddObserver(base::MakeUnique<TestPageLoadMetricsObserver>( |  136     tracker->AddObserver(base::MakeUnique<TestPageLoadMetricsObserver>( | 
|  137         web_contents_, &updated_timings_, &updated_subframe_timings_, |  137         web_contents_, &updated_timings_, &updated_subframe_timings_, | 
|  138         &complete_timings_, &observed_committed_urls_)); |  138         &complete_timings_, &observed_committed_urls_)); | 
|  139     tracker->AddObserver(base::MakeUnique<FilteringPageLoadMetricsObserver>( |  139     tracker->AddObserver(base::MakeUnique<FilteringPageLoadMetricsObserver>( | 
|  140         &completed_filtered_urls_)); |  140         &completed_filtered_urls_)); | 
|  141   } |  141   } | 
|  142   const std::vector<PageLoadTiming>& updated_timings() const { |  142   const std::vector<mojom::PageLoadTimingPtr>& updated_timings() const { | 
|  143     return updated_timings_; |  143     return updated_timings_; | 
|  144   } |  144   } | 
|  145   const std::vector<PageLoadTiming>& complete_timings() const { |  145   const std::vector<mojom::PageLoadTimingPtr>& complete_timings() const { | 
|  146     return complete_timings_; |  146     return complete_timings_; | 
|  147   } |  147   } | 
|  148   const std::vector<PageLoadTiming>& updated_subframe_timings() const { |  148   const std::vector<mojom::PageLoadTimingPtr>& updated_subframe_timings() | 
 |  149       const { | 
|  149     return updated_subframe_timings_; |  150     return updated_subframe_timings_; | 
|  150   } |  151   } | 
|  151  |  152  | 
|  152   // currently_committed_urls passed to OnStart(). |  153   // currently_committed_urls passed to OnStart(). | 
|  153   const std::vector<GURL>& observed_committed_urls_from_on_start() const { |  154   const std::vector<GURL>& observed_committed_urls_from_on_start() const { | 
|  154     return observed_committed_urls_; |  155     return observed_committed_urls_; | 
|  155   } |  156   } | 
|  156  |  157  | 
|  157   // committed URLs passed to FilteringPageLoadMetricsObserver::OnComplete(). |  158   // committed URLs passed to FilteringPageLoadMetricsObserver::OnComplete(). | 
|  158   const std::vector<GURL>& completed_filtered_urls() const { |  159   const std::vector<GURL>& completed_filtered_urls() const { | 
|  159     return completed_filtered_urls_; |  160     return completed_filtered_urls_; | 
|  160   } |  161   } | 
|  161  |  162  | 
|  162  private: |  163  private: | 
|  163   std::vector<PageLoadTiming> updated_timings_; |  164   std::vector<mojom::PageLoadTimingPtr> updated_timings_; | 
|  164   std::vector<PageLoadTiming> updated_subframe_timings_; |  165   std::vector<mojom::PageLoadTimingPtr> updated_subframe_timings_; | 
|  165   std::vector<PageLoadTiming> complete_timings_; |  166   std::vector<mojom::PageLoadTimingPtr> complete_timings_; | 
|  166   std::vector<GURL> observed_committed_urls_; |  167   std::vector<GURL> observed_committed_urls_; | 
|  167   std::vector<GURL> completed_filtered_urls_; |  168   std::vector<GURL> completed_filtered_urls_; | 
|  168   content::WebContents* web_contents_; |  169   content::WebContents* web_contents_; | 
|  169   bool is_ntp_; |  170   bool is_ntp_; | 
|  170 }; |  171 }; | 
|  171  |  172  | 
|  172 }  //  namespace |  173 }  //  namespace | 
|  173  |  174  | 
|  174 class MetricsWebContentsObserverTest : public ChromeRenderViewHostTestHarness { |  175 class MetricsWebContentsObserverTest : public ChromeRenderViewHostTestHarness { | 
|  175  public: |  176  public: | 
|  176   MetricsWebContentsObserverTest() : num_errors_(0) {} |  177   MetricsWebContentsObserverTest() : num_errors_(0) {} | 
|  177  |  178  | 
|  178   void SetUp() override { |  179   void SetUp() override { | 
|  179     ChromeRenderViewHostTestHarness::SetUp(); |  180     ChromeRenderViewHostTestHarness::SetUp(); | 
|  180     AttachObserver(); |  181     AttachObserver(); | 
|  181   } |  182   } | 
|  182  |  183  | 
|  183   void NavigateToUntrackedUrl() { |  184   void NavigateToUntrackedUrl() { | 
|  184     content::WebContentsTester::For(web_contents()) |  185     content::WebContentsTester::For(web_contents()) | 
|  185         ->NavigateAndCommit(GURL(url::kAboutBlankURL)); |  186         ->NavigateAndCommit(GURL(url::kAboutBlankURL)); | 
|  186   } |  187   } | 
|  187  |  188  | 
|  188   void SimulateTimingUpdate(const PageLoadTiming& timing) { |  189   void SimulateTimingUpdate(const mojom::PageLoadTiming& timing) { | 
|  189     SimulateTimingUpdate(timing, web_contents()->GetMainFrame()); |  190     SimulateTimingUpdate(timing, web_contents()->GetMainFrame()); | 
|  190   } |  191   } | 
|  191  |  192  | 
|  192   void SimulateTimingUpdate(const PageLoadTiming& timing, |  193   void SimulateTimingUpdate(const mojom::PageLoadTiming& timing, | 
|  193                             content::RenderFrameHost* render_frame_host) { |  194                             content::RenderFrameHost* render_frame_host) { | 
|  194     observer_->OnTimingUpdated(render_frame_host, timing, PageLoadMetadata()); |  195     observer_->OnTimingUpdated(render_frame_host, timing, | 
 |  196                                mojom::PageLoadMetadata()); | 
|  195   } |  197   } | 
|  196  |  198  | 
|  197   void AttachObserver() { |  199   void AttachObserver() { | 
|  198     embedder_interface_ = |  200     embedder_interface_ = | 
|  199         new TestPageLoadMetricsEmbedderInterface(web_contents()); |  201         new TestPageLoadMetricsEmbedderInterface(web_contents()); | 
|  200     // Owned by the web_contents. Tests must be careful not to call |  202     // Owned by the web_contents. Tests must be careful not to call | 
|  201     // SimulateTimingUpdate after they call DeleteContents() without also |  203     // SimulateTimingUpdate after they call DeleteContents() without also | 
|  202     // calling AttachObserver() again. Otherwise they will use-after-free the |  204     // calling AttachObserver() again. Otherwise they will use-after-free the | 
|  203     // observer_. |  205     // observer_. | 
|  204     observer_ = MetricsWebContentsObserver::CreateForWebContents( |  206     observer_ = MetricsWebContentsObserver::CreateForWebContents( | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|  215     histogram_tester_.ExpectTotalCount(internal::kErrorEvents, num_errors_); |  217     histogram_tester_.ExpectTotalCount(internal::kErrorEvents, num_errors_); | 
|  216   } |  218   } | 
|  217  |  219  | 
|  218   void CheckNoErrorEvents() { |  220   void CheckNoErrorEvents() { | 
|  219     histogram_tester_.ExpectTotalCount(internal::kErrorEvents, 0); |  221     histogram_tester_.ExpectTotalCount(internal::kErrorEvents, 0); | 
|  220   } |  222   } | 
|  221  |  223  | 
|  222   int CountEmptyCompleteTimingReported() { |  224   int CountEmptyCompleteTimingReported() { | 
|  223     int empty = 0; |  225     int empty = 0; | 
|  224     for (const auto& timing : embedder_interface_->complete_timings()) { |  226     for (const auto& timing : embedder_interface_->complete_timings()) { | 
|  225       if (timing.IsEmpty()) |  227       if (page_load_metrics::IsEmpty(*timing)) | 
|  226         ++empty; |  228         ++empty; | 
|  227     } |  229     } | 
|  228     return empty; |  230     return empty; | 
|  229   } |  231   } | 
|  230  |  232  | 
|  231   const std::vector<PageLoadTiming>& updated_timings() const { |  233   const std::vector<mojom::PageLoadTimingPtr>& updated_timings() const { | 
|  232     return embedder_interface_->updated_timings(); |  234     return embedder_interface_->updated_timings(); | 
|  233   } |  235   } | 
|  234   const std::vector<PageLoadTiming>& complete_timings() const { |  236   const std::vector<mojom::PageLoadTimingPtr>& complete_timings() const { | 
|  235     return embedder_interface_->complete_timings(); |  237     return embedder_interface_->complete_timings(); | 
|  236   } |  238   } | 
|  237   const std::vector<PageLoadTiming>& updated_subframe_timings() const { |  239   const std::vector<mojom::PageLoadTimingPtr>& updated_subframe_timings() | 
 |  240       const { | 
|  238     return embedder_interface_->updated_subframe_timings(); |  241     return embedder_interface_->updated_subframe_timings(); | 
|  239   } |  242   } | 
|  240   int CountCompleteTimingReported() { return complete_timings().size(); } |  243   int CountCompleteTimingReported() { return complete_timings().size(); } | 
|  241   int CountUpdatedTimingReported() { return updated_timings().size(); } |  244   int CountUpdatedTimingReported() { return updated_timings().size(); } | 
|  242   int CountUpdatedSubFrameTimingReported() { |  245   int CountUpdatedSubFrameTimingReported() { | 
|  243     return updated_subframe_timings().size(); |  246     return updated_subframe_timings().size(); | 
|  244   } |  247   } | 
|  245  |  248  | 
|  246   const std::vector<GURL>& observed_committed_urls_from_on_start() const { |  249   const std::vector<GURL>& observed_committed_urls_from_on_start() const { | 
|  247     return embedder_interface_->observed_committed_urls_from_on_start(); |  250     return embedder_interface_->observed_committed_urls_from_on_start(); | 
|  248   } |  251   } | 
|  249  |  252  | 
|  250   const std::vector<GURL>& completed_filtered_urls() const { |  253   const std::vector<GURL>& completed_filtered_urls() const { | 
|  251     return embedder_interface_->completed_filtered_urls(); |  254     return embedder_interface_->completed_filtered_urls(); | 
|  252   } |  255   } | 
|  253  |  256  | 
|  254  protected: |  257  protected: | 
|  255   base::HistogramTester histogram_tester_; |  258   base::HistogramTester histogram_tester_; | 
|  256   TestPageLoadMetricsEmbedderInterface* embedder_interface_; |  259   TestPageLoadMetricsEmbedderInterface* embedder_interface_; | 
|  257   MetricsWebContentsObserver* observer_; |  260   MetricsWebContentsObserver* observer_; | 
|  258  |  261  | 
|  259  private: |  262  private: | 
|  260   int num_errors_; |  263   int num_errors_; | 
|  261  |  264  | 
|  262   DISALLOW_COPY_AND_ASSIGN(MetricsWebContentsObserverTest); |  265   DISALLOW_COPY_AND_ASSIGN(MetricsWebContentsObserverTest); | 
|  263 }; |  266 }; | 
|  264  |  267  | 
|  265 TEST_F(MetricsWebContentsObserverTest, SuccessfulMainFrameNavigation) { |  268 TEST_F(MetricsWebContentsObserverTest, SuccessfulMainFrameNavigation) { | 
|  266   PageLoadTiming timing; |  269   mojom::PageLoadTiming timing; | 
 |  270   page_load_metrics::InitPageLoadTimingForTest(&timing); | 
|  267   timing.navigation_start = base::Time::FromDoubleT(1); |  271   timing.navigation_start = base::Time::FromDoubleT(1); | 
|  268  |  272  | 
|  269   content::WebContentsTester* web_contents_tester = |  273   content::WebContentsTester* web_contents_tester = | 
|  270       content::WebContentsTester::For(web_contents()); |  274       content::WebContentsTester::For(web_contents()); | 
|  271  |  275  | 
|  272   ASSERT_TRUE(observed_committed_urls_from_on_start().empty()); |  276   ASSERT_TRUE(observed_committed_urls_from_on_start().empty()); | 
|  273   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); |  277   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | 
|  274   ASSERT_EQ(1u, observed_committed_urls_from_on_start().size()); |  278   ASSERT_EQ(1u, observed_committed_urls_from_on_start().size()); | 
|  275   ASSERT_TRUE(observed_committed_urls_from_on_start().at(0).is_empty()); |  279   ASSERT_TRUE(observed_committed_urls_from_on_start().at(0).is_empty()); | 
|  276  |  280  | 
|  277   ASSERT_EQ(0, CountUpdatedTimingReported()); |  281   ASSERT_EQ(0, CountUpdatedTimingReported()); | 
|  278   SimulateTimingUpdate(timing); |  282   SimulateTimingUpdate(timing); | 
|  279   ASSERT_EQ(1, CountUpdatedTimingReported()); |  283   ASSERT_EQ(1, CountUpdatedTimingReported()); | 
|  280   ASSERT_EQ(0, CountCompleteTimingReported()); |  284   ASSERT_EQ(0, CountCompleteTimingReported()); | 
|  281  |  285  | 
|  282   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); |  286   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); | 
|  283   ASSERT_EQ(1, CountCompleteTimingReported()); |  287   ASSERT_EQ(1, CountCompleteTimingReported()); | 
|  284   ASSERT_EQ(0, CountEmptyCompleteTimingReported()); |  288   ASSERT_EQ(0, CountEmptyCompleteTimingReported()); | 
|  285   ASSERT_EQ(2u, observed_committed_urls_from_on_start().size()); |  289   ASSERT_EQ(2u, observed_committed_urls_from_on_start().size()); | 
|  286   ASSERT_EQ(kDefaultTestUrl, |  290   ASSERT_EQ(kDefaultTestUrl, | 
|  287             observed_committed_urls_from_on_start().at(1).spec()); |  291             observed_committed_urls_from_on_start().at(1).spec()); | 
|  288   ASSERT_EQ(1, CountUpdatedTimingReported()); |  292   ASSERT_EQ(1, CountUpdatedTimingReported()); | 
|  289   ASSERT_EQ(0, CountUpdatedSubFrameTimingReported()); |  293   ASSERT_EQ(0, CountUpdatedSubFrameTimingReported()); | 
|  290  |  294  | 
|  291   CheckNoErrorEvents(); |  295   CheckNoErrorEvents(); | 
|  292 } |  296 } | 
|  293  |  297  | 
|  294 TEST_F(MetricsWebContentsObserverTest, SubFrame) { |  298 TEST_F(MetricsWebContentsObserverTest, SubFrame) { | 
|  295   PageLoadTiming timing; |  299   mojom::PageLoadTiming timing; | 
 |  300   page_load_metrics::InitPageLoadTimingForTest(&timing); | 
|  296   timing.navigation_start = base::Time::FromDoubleT(1); |  301   timing.navigation_start = base::Time::FromDoubleT(1); | 
|  297   timing.response_start = base::TimeDelta::FromMilliseconds(10); |  302   timing.response_start = base::TimeDelta::FromMilliseconds(10); | 
|  298   timing.parse_timing.parse_start = base::TimeDelta::FromMilliseconds(20); |  303   timing.parse_timing->parse_start = base::TimeDelta::FromMilliseconds(20); | 
|  299   timing.document_timing.first_layout = base::TimeDelta::FromMilliseconds(30); |  304   timing.document_timing->first_layout = base::TimeDelta::FromMilliseconds(30); | 
|  300  |  305  | 
|  301   content::WebContentsTester* web_contents_tester = |  306   content::WebContentsTester* web_contents_tester = | 
|  302       content::WebContentsTester::For(web_contents()); |  307       content::WebContentsTester::For(web_contents()); | 
|  303   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); |  308   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | 
|  304   SimulateTimingUpdate(timing); |  309   SimulateTimingUpdate(timing); | 
|  305  |  310  | 
|  306   ASSERT_EQ(1, CountUpdatedTimingReported()); |  311   ASSERT_EQ(1, CountUpdatedTimingReported()); | 
|  307   EXPECT_EQ(timing, updated_timings().back()); |  312   EXPECT_TRUE(timing.Equals(*updated_timings().back())); | 
|  308  |  313  | 
|  309   content::RenderFrameHostTester* rfh_tester = |  314   content::RenderFrameHostTester* rfh_tester = | 
|  310       content::RenderFrameHostTester::For(main_rfh()); |  315       content::RenderFrameHostTester::For(main_rfh()); | 
|  311   content::RenderFrameHost* subframe = rfh_tester->AppendChild("subframe"); |  316   content::RenderFrameHost* subframe = rfh_tester->AppendChild("subframe"); | 
|  312  |  317  | 
|  313   // Dispatch a timing update for the child frame that includes a first paint. |  318   // Dispatch a timing update for the child frame that includes a first paint. | 
|  314   PageLoadTiming subframe_timing; |  319   mojom::PageLoadTiming subframe_timing; | 
 |  320   page_load_metrics::InitPageLoadTimingForTest(&subframe_timing); | 
|  315   subframe_timing.navigation_start = base::Time::FromDoubleT(2); |  321   subframe_timing.navigation_start = base::Time::FromDoubleT(2); | 
|  316   subframe_timing.response_start = base::TimeDelta::FromMilliseconds(10); |  322   subframe_timing.response_start = base::TimeDelta::FromMilliseconds(10); | 
|  317   subframe_timing.parse_timing.parse_start = |  323   subframe_timing.parse_timing->parse_start = | 
|  318       base::TimeDelta::FromMilliseconds(20); |  324       base::TimeDelta::FromMilliseconds(20); | 
|  319   subframe_timing.document_timing.first_layout = |  325   subframe_timing.document_timing->first_layout = | 
|  320       base::TimeDelta::FromMilliseconds(30); |  326       base::TimeDelta::FromMilliseconds(30); | 
|  321   subframe_timing.paint_timing.first_paint = |  327   subframe_timing.paint_timing->first_paint = | 
|  322       base::TimeDelta::FromMilliseconds(40); |  328       base::TimeDelta::FromMilliseconds(40); | 
|  323   content::RenderFrameHostTester* subframe_tester = |  329   content::RenderFrameHostTester* subframe_tester = | 
|  324       content::RenderFrameHostTester::For(subframe); |  330       content::RenderFrameHostTester::For(subframe); | 
|  325   subframe_tester->SimulateNavigationStart(GURL(kDefaultTestUrl2)); |  331   subframe_tester->SimulateNavigationStart(GURL(kDefaultTestUrl2)); | 
|  326   subframe_tester->SimulateNavigationCommit(GURL(kDefaultTestUrl2)); |  332   subframe_tester->SimulateNavigationCommit(GURL(kDefaultTestUrl2)); | 
|  327   SimulateTimingUpdate(subframe_timing, subframe); |  333   SimulateTimingUpdate(subframe_timing, subframe); | 
|  328   subframe_tester->SimulateNavigationStop(); |  334   subframe_tester->SimulateNavigationStop(); | 
|  329  |  335  | 
|  330   ASSERT_EQ(1, CountUpdatedSubFrameTimingReported()); |  336   ASSERT_EQ(1, CountUpdatedSubFrameTimingReported()); | 
|  331   EXPECT_EQ(subframe_timing, updated_subframe_timings().back()); |  337   EXPECT_TRUE(subframe_timing.Equals(*updated_subframe_timings().back())); | 
|  332  |  338  | 
|  333   // The subframe update which included a paint should have also triggered |  339   // The subframe update which included a paint should have also triggered | 
|  334   // a main frame update, which includes a first paint. |  340   // a main frame update, which includes a first paint. | 
|  335   ASSERT_EQ(2, CountUpdatedTimingReported()); |  341   ASSERT_EQ(2, CountUpdatedTimingReported()); | 
|  336   EXPECT_NE(timing, updated_timings().back()); |  342   EXPECT_FALSE(timing.Equals(*updated_timings().back())); | 
|  337   EXPECT_TRUE(updated_timings().back().paint_timing.first_paint); |  343   EXPECT_TRUE(updated_timings().back()->paint_timing->first_paint); | 
|  338  |  344  | 
|  339   // Navigate again to see if the timing updated for a subframe message. |  345   // Navigate again to see if the timing updated for a subframe message. | 
|  340   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); |  346   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); | 
|  341  |  347  | 
|  342   ASSERT_EQ(1, CountCompleteTimingReported()); |  348   ASSERT_EQ(1, CountCompleteTimingReported()); | 
|  343   ASSERT_EQ(2, CountUpdatedTimingReported()); |  349   ASSERT_EQ(2, CountUpdatedTimingReported()); | 
|  344   ASSERT_EQ(0, CountEmptyCompleteTimingReported()); |  350   ASSERT_EQ(0, CountEmptyCompleteTimingReported()); | 
|  345  |  351  | 
|  346   ASSERT_EQ(1, CountUpdatedSubFrameTimingReported()); |  352   ASSERT_EQ(1, CountUpdatedSubFrameTimingReported()); | 
|  347   EXPECT_EQ(subframe_timing, updated_subframe_timings().back()); |  353   EXPECT_TRUE(subframe_timing.Equals(*updated_subframe_timings().back())); | 
|  348  |  354  | 
|  349   CheckNoErrorEvents(); |  355   CheckNoErrorEvents(); | 
|  350 } |  356 } | 
|  351  |  357  | 
|  352 TEST_F(MetricsWebContentsObserverTest, SameDocumentNoTrigger) { |  358 TEST_F(MetricsWebContentsObserverTest, SameDocumentNoTrigger) { | 
|  353   PageLoadTiming timing; |  359   mojom::PageLoadTiming timing; | 
 |  360   page_load_metrics::InitPageLoadTimingForTest(&timing); | 
|  354   timing.navigation_start = base::Time::FromDoubleT(1); |  361   timing.navigation_start = base::Time::FromDoubleT(1); | 
|  355  |  362  | 
|  356   content::WebContentsTester* web_contents_tester = |  363   content::WebContentsTester* web_contents_tester = | 
|  357       content::WebContentsTester::For(web_contents()); |  364       content::WebContentsTester::For(web_contents()); | 
|  358   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); |  365   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | 
|  359   ASSERT_EQ(0, CountUpdatedTimingReported()); |  366   ASSERT_EQ(0, CountUpdatedTimingReported()); | 
|  360   SimulateTimingUpdate(timing); |  367   SimulateTimingUpdate(timing); | 
|  361   ASSERT_EQ(1, CountUpdatedTimingReported()); |  368   ASSERT_EQ(1, CountUpdatedTimingReported()); | 
|  362   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrlAnchor)); |  369   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrlAnchor)); | 
|  363   // Send the same timing update. The original tracker for kDefaultTestUrl |  370   // Send the same timing update. The original tracker for kDefaultTestUrl | 
|  364   // should dedup the update, and the tracker for kDefaultTestUrlAnchor should |  371   // should dedup the update, and the tracker for kDefaultTestUrlAnchor should | 
|  365   // have been destroyed as a result of its being a same page navigation, so |  372   // have been destroyed as a result of its being a same page navigation, so | 
|  366   // CountUpdatedTimingReported() should continue to return 1. |  373   // CountUpdatedTimingReported() should continue to return 1. | 
|  367   SimulateTimingUpdate(timing); |  374   SimulateTimingUpdate(timing); | 
|  368  |  375  | 
|  369   ASSERT_EQ(1, CountUpdatedTimingReported()); |  376   ASSERT_EQ(1, CountUpdatedTimingReported()); | 
|  370   ASSERT_EQ(0, CountCompleteTimingReported()); |  377   ASSERT_EQ(0, CountCompleteTimingReported()); | 
|  371  |  378  | 
|  372   // Navigate again to force histogram logging. |  379   // Navigate again to force histogram logging. | 
|  373   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); |  380   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); | 
|  374  |  381  | 
|  375   // A same page navigation shouldn't trigger logging UMA for the original. |  382   // A same page navigation shouldn't trigger logging UMA for the original. | 
|  376   ASSERT_EQ(1, CountUpdatedTimingReported()); |  383   ASSERT_EQ(1, CountUpdatedTimingReported()); | 
|  377   ASSERT_EQ(1, CountCompleteTimingReported()); |  384   ASSERT_EQ(1, CountCompleteTimingReported()); | 
|  378   ASSERT_EQ(0, CountEmptyCompleteTimingReported()); |  385   ASSERT_EQ(0, CountEmptyCompleteTimingReported()); | 
|  379   CheckNoErrorEvents(); |  386   CheckNoErrorEvents(); | 
|  380 } |  387 } | 
|  381  |  388  | 
|  382 TEST_F(MetricsWebContentsObserverTest, DontLogNewTabPage) { |  389 TEST_F(MetricsWebContentsObserverTest, DontLogNewTabPage) { | 
|  383   PageLoadTiming timing; |  390   mojom::PageLoadTiming timing; | 
 |  391   page_load_metrics::InitPageLoadTimingForTest(&timing); | 
|  384   timing.navigation_start = base::Time::FromDoubleT(1); |  392   timing.navigation_start = base::Time::FromDoubleT(1); | 
|  385  |  393  | 
|  386   content::WebContentsTester* web_contents_tester = |  394   content::WebContentsTester* web_contents_tester = | 
|  387       content::WebContentsTester::For(web_contents()); |  395       content::WebContentsTester::For(web_contents()); | 
|  388   embedder_interface_->set_is_ntp(true); |  396   embedder_interface_->set_is_ntp(true); | 
|  389  |  397  | 
|  390   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); |  398   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | 
|  391   SimulateTimingUpdate(timing); |  399   SimulateTimingUpdate(timing); | 
|  392   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); |  400   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); | 
|  393   ASSERT_EQ(0, CountUpdatedTimingReported()); |  401   ASSERT_EQ(0, CountUpdatedTimingReported()); | 
|  394   ASSERT_EQ(0, CountCompleteTimingReported()); |  402   ASSERT_EQ(0, CountCompleteTimingReported()); | 
|  395   CheckErrorEvent(ERR_IPC_WITH_NO_RELEVANT_LOAD, 1); |  403   CheckErrorEvent(ERR_IPC_WITH_NO_RELEVANT_LOAD, 1); | 
|  396   CheckTotalErrorEvents(); |  404   CheckTotalErrorEvents(); | 
|  397 } |  405 } | 
|  398  |  406  | 
|  399 TEST_F(MetricsWebContentsObserverTest, DontLogIrrelevantNavigation) { |  407 TEST_F(MetricsWebContentsObserverTest, DontLogIrrelevantNavigation) { | 
|  400   PageLoadTiming timing; |  408   mojom::PageLoadTiming timing; | 
 |  409   page_load_metrics::InitPageLoadTimingForTest(&timing); | 
|  401   timing.navigation_start = base::Time::FromDoubleT(10); |  410   timing.navigation_start = base::Time::FromDoubleT(10); | 
|  402  |  411  | 
|  403   content::WebContentsTester* web_contents_tester = |  412   content::WebContentsTester* web_contents_tester = | 
|  404       content::WebContentsTester::For(web_contents()); |  413       content::WebContentsTester::For(web_contents()); | 
|  405  |  414  | 
|  406   GURL about_blank_url = GURL("about:blank"); |  415   GURL about_blank_url = GURL("about:blank"); | 
|  407   web_contents_tester->NavigateAndCommit(about_blank_url); |  416   web_contents_tester->NavigateAndCommit(about_blank_url); | 
|  408   SimulateTimingUpdate(timing); |  417   SimulateTimingUpdate(timing); | 
|  409   ASSERT_EQ(0, CountUpdatedTimingReported()); |  418   ASSERT_EQ(0, CountUpdatedTimingReported()); | 
|  410   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); |  419   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | 
|  411   ASSERT_EQ(0, CountUpdatedTimingReported()); |  420   ASSERT_EQ(0, CountUpdatedTimingReported()); | 
|  412   ASSERT_EQ(0, CountCompleteTimingReported()); |  421   ASSERT_EQ(0, CountCompleteTimingReported()); | 
|  413  |  422  | 
|  414   CheckErrorEvent(ERR_IPC_FROM_BAD_URL_SCHEME, 1); |  423   CheckErrorEvent(ERR_IPC_FROM_BAD_URL_SCHEME, 1); | 
|  415   CheckErrorEvent(ERR_IPC_WITH_NO_RELEVANT_LOAD, 1); |  424   CheckErrorEvent(ERR_IPC_WITH_NO_RELEVANT_LOAD, 1); | 
|  416   CheckTotalErrorEvents(); |  425   CheckTotalErrorEvents(); | 
|  417 } |  426 } | 
|  418  |  427  | 
|  419 TEST_F(MetricsWebContentsObserverTest, EmptyTimingError) { |  428 TEST_F(MetricsWebContentsObserverTest, EmptyTimingError) { | 
|  420   PageLoadTiming timing; |  429   mojom::PageLoadTiming timing; | 
 |  430   page_load_metrics::InitPageLoadTimingForTest(&timing); | 
|  421  |  431  | 
|  422   content::WebContentsTester* web_contents_tester = |  432   content::WebContentsTester* web_contents_tester = | 
|  423       content::WebContentsTester::For(web_contents()); |  433       content::WebContentsTester::For(web_contents()); | 
|  424  |  434  | 
|  425   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); |  435   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | 
|  426   SimulateTimingUpdate(timing); |  436   SimulateTimingUpdate(timing); | 
|  427   ASSERT_EQ(0, CountUpdatedTimingReported()); |  437   ASSERT_EQ(0, CountUpdatedTimingReported()); | 
|  428   NavigateToUntrackedUrl(); |  438   NavigateToUntrackedUrl(); | 
|  429   ASSERT_EQ(0, CountUpdatedTimingReported()); |  439   ASSERT_EQ(0, CountUpdatedTimingReported()); | 
|  430   ASSERT_EQ(1, CountCompleteTimingReported()); |  440   ASSERT_EQ(1, CountCompleteTimingReported()); | 
|  431  |  441  | 
|  432   CheckErrorEvent(ERR_BAD_TIMING_IPC_INVALID_TIMING, 1); |  442   CheckErrorEvent(ERR_BAD_TIMING_IPC_INVALID_TIMING, 1); | 
|  433   CheckErrorEvent(ERR_NO_IPCS_RECEIVED, 1); |  443   CheckErrorEvent(ERR_NO_IPCS_RECEIVED, 1); | 
|  434   CheckTotalErrorEvents(); |  444   CheckTotalErrorEvents(); | 
|  435  |  445  | 
|  436   histogram_tester_.ExpectTotalCount( |  446   histogram_tester_.ExpectTotalCount( | 
|  437       page_load_metrics::internal::kPageLoadTimingStatus, 1); |  447       page_load_metrics::internal::kPageLoadTimingStatus, 1); | 
|  438   histogram_tester_.ExpectBucketCount( |  448   histogram_tester_.ExpectBucketCount( | 
|  439       page_load_metrics::internal::kPageLoadTimingStatus, |  449       page_load_metrics::internal::kPageLoadTimingStatus, | 
|  440       page_load_metrics::internal::INVALID_EMPTY_TIMING, 1); |  450       page_load_metrics::internal::INVALID_EMPTY_TIMING, 1); | 
|  441 } |  451 } | 
|  442  |  452  | 
|  443 TEST_F(MetricsWebContentsObserverTest, NullNavigationStartError) { |  453 TEST_F(MetricsWebContentsObserverTest, NullNavigationStartError) { | 
|  444   PageLoadTiming timing; |  454   mojom::PageLoadTiming timing; | 
|  445   timing.parse_timing.parse_start = base::TimeDelta::FromMilliseconds(1); |  455   page_load_metrics::InitPageLoadTimingForTest(&timing); | 
 |  456   timing.parse_timing->parse_start = base::TimeDelta::FromMilliseconds(1); | 
|  446  |  457  | 
|  447   content::WebContentsTester* web_contents_tester = |  458   content::WebContentsTester* web_contents_tester = | 
|  448       content::WebContentsTester::For(web_contents()); |  459       content::WebContentsTester::For(web_contents()); | 
|  449  |  460  | 
|  450   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); |  461   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | 
|  451   SimulateTimingUpdate(timing); |  462   SimulateTimingUpdate(timing); | 
|  452   ASSERT_EQ(0, CountUpdatedTimingReported()); |  463   ASSERT_EQ(0, CountUpdatedTimingReported()); | 
|  453   NavigateToUntrackedUrl(); |  464   NavigateToUntrackedUrl(); | 
|  454   ASSERT_EQ(0, CountUpdatedTimingReported()); |  465   ASSERT_EQ(0, CountUpdatedTimingReported()); | 
|  455   ASSERT_EQ(1, CountCompleteTimingReported()); |  466   ASSERT_EQ(1, CountCompleteTimingReported()); | 
|  456  |  467  | 
|  457   CheckErrorEvent(ERR_BAD_TIMING_IPC_INVALID_TIMING, 1); |  468   CheckErrorEvent(ERR_BAD_TIMING_IPC_INVALID_TIMING, 1); | 
|  458   CheckErrorEvent(ERR_NO_IPCS_RECEIVED, 1); |  469   CheckErrorEvent(ERR_NO_IPCS_RECEIVED, 1); | 
|  459   CheckTotalErrorEvents(); |  470   CheckTotalErrorEvents(); | 
|  460  |  471  | 
|  461   histogram_tester_.ExpectTotalCount( |  472   histogram_tester_.ExpectTotalCount( | 
|  462       page_load_metrics::internal::kPageLoadTimingStatus, 1); |  473       page_load_metrics::internal::kPageLoadTimingStatus, 1); | 
|  463   histogram_tester_.ExpectBucketCount( |  474   histogram_tester_.ExpectBucketCount( | 
|  464       page_load_metrics::internal::kPageLoadTimingStatus, |  475       page_load_metrics::internal::kPageLoadTimingStatus, | 
|  465       page_load_metrics::internal::INVALID_NULL_NAVIGATION_START, 1); |  476       page_load_metrics::internal::INVALID_NULL_NAVIGATION_START, 1); | 
|  466 } |  477 } | 
|  467  |  478  | 
|  468 TEST_F(MetricsWebContentsObserverTest, TimingOrderError) { |  479 TEST_F(MetricsWebContentsObserverTest, TimingOrderError) { | 
|  469   PageLoadTiming timing; |  480   mojom::PageLoadTiming timing; | 
 |  481   page_load_metrics::InitPageLoadTimingForTest(&timing); | 
|  470   timing.navigation_start = base::Time::FromDoubleT(1); |  482   timing.navigation_start = base::Time::FromDoubleT(1); | 
|  471   timing.parse_timing.parse_stop = base::TimeDelta::FromMilliseconds(1); |  483   timing.parse_timing->parse_stop = base::TimeDelta::FromMilliseconds(1); | 
|  472  |  484  | 
|  473   content::WebContentsTester* web_contents_tester = |  485   content::WebContentsTester* web_contents_tester = | 
|  474       content::WebContentsTester::For(web_contents()); |  486       content::WebContentsTester::For(web_contents()); | 
|  475  |  487  | 
|  476   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); |  488   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | 
|  477   SimulateTimingUpdate(timing); |  489   SimulateTimingUpdate(timing); | 
|  478   ASSERT_EQ(0, CountUpdatedTimingReported()); |  490   ASSERT_EQ(0, CountUpdatedTimingReported()); | 
|  479   NavigateToUntrackedUrl(); |  491   NavigateToUntrackedUrl(); | 
|  480   ASSERT_EQ(0, CountUpdatedTimingReported()); |  492   ASSERT_EQ(0, CountUpdatedTimingReported()); | 
|  481   ASSERT_EQ(1, CountCompleteTimingReported()); |  493   ASSERT_EQ(1, CountCompleteTimingReported()); | 
|  482  |  494  | 
|  483   CheckErrorEvent(ERR_BAD_TIMING_IPC_INVALID_TIMING, 1); |  495   CheckErrorEvent(ERR_BAD_TIMING_IPC_INVALID_TIMING, 1); | 
|  484   CheckErrorEvent(ERR_NO_IPCS_RECEIVED, 1); |  496   CheckErrorEvent(ERR_NO_IPCS_RECEIVED, 1); | 
|  485   CheckTotalErrorEvents(); |  497   CheckTotalErrorEvents(); | 
|  486  |  498  | 
|  487   histogram_tester_.ExpectTotalCount( |  499   histogram_tester_.ExpectTotalCount( | 
|  488       page_load_metrics::internal::kPageLoadTimingStatus, 1); |  500       page_load_metrics::internal::kPageLoadTimingStatus, 1); | 
|  489   histogram_tester_.ExpectBucketCount( |  501   histogram_tester_.ExpectBucketCount( | 
|  490       page_load_metrics::internal::kPageLoadTimingStatus, |  502       page_load_metrics::internal::kPageLoadTimingStatus, | 
|  491       page_load_metrics::internal::INVALID_ORDER_PARSE_START_PARSE_STOP, 1); |  503       page_load_metrics::internal::INVALID_ORDER_PARSE_START_PARSE_STOP, 1); | 
|  492 } |  504 } | 
|  493  |  505  | 
|  494 TEST_F(MetricsWebContentsObserverTest, BadIPC) { |  506 TEST_F(MetricsWebContentsObserverTest, BadIPC) { | 
|  495   PageLoadTiming timing; |  507   mojom::PageLoadTiming timing; | 
 |  508   page_load_metrics::InitPageLoadTimingForTest(&timing); | 
|  496   timing.navigation_start = base::Time::FromDoubleT(10); |  509   timing.navigation_start = base::Time::FromDoubleT(10); | 
|  497   PageLoadTiming timing2; |  510   mojom::PageLoadTiming timing2; | 
 |  511   page_load_metrics::InitPageLoadTimingForTest(&timing2); | 
|  498   timing2.navigation_start = base::Time::FromDoubleT(100); |  512   timing2.navigation_start = base::Time::FromDoubleT(100); | 
|  499  |  513  | 
|  500   content::WebContentsTester* web_contents_tester = |  514   content::WebContentsTester* web_contents_tester = | 
|  501       content::WebContentsTester::For(web_contents()); |  515       content::WebContentsTester::For(web_contents()); | 
|  502   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); |  516   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | 
|  503  |  517  | 
|  504   SimulateTimingUpdate(timing); |  518   SimulateTimingUpdate(timing); | 
|  505   ASSERT_EQ(1, CountUpdatedTimingReported()); |  519   ASSERT_EQ(1, CountUpdatedTimingReported()); | 
|  506   SimulateTimingUpdate(timing2); |  520   SimulateTimingUpdate(timing2); | 
|  507   ASSERT_EQ(1, CountUpdatedTimingReported()); |  521   ASSERT_EQ(1, CountUpdatedTimingReported()); | 
|  508  |  522  | 
|  509   CheckErrorEvent(ERR_BAD_TIMING_IPC_INVALID_TIMING_DESCENDENT, 1); |  523   CheckErrorEvent(ERR_BAD_TIMING_IPC_INVALID_TIMING_DESCENDENT, 1); | 
|  510   CheckTotalErrorEvents(); |  524   CheckTotalErrorEvents(); | 
|  511 } |  525 } | 
|  512  |  526  | 
|  513 TEST_F(MetricsWebContentsObserverTest, ObservePartialNavigation) { |  527 TEST_F(MetricsWebContentsObserverTest, ObservePartialNavigation) { | 
|  514   // Reset the state of the tests, and attach the MetricsWebContentsObserver in |  528   // Reset the state of the tests, and attach the MetricsWebContentsObserver in | 
|  515   // the middle of a navigation. This tests that the class is robust to only |  529   // the middle of a navigation. This tests that the class is robust to only | 
|  516   // observing some of a navigation. |  530   // observing some of a navigation. | 
|  517   DeleteContents(); |  531   DeleteContents(); | 
|  518   SetContents(CreateTestWebContents()); |  532   SetContents(CreateTestWebContents()); | 
|  519  |  533  | 
|  520   PageLoadTiming timing; |  534   mojom::PageLoadTiming timing; | 
 |  535   page_load_metrics::InitPageLoadTimingForTest(&timing); | 
|  521   timing.navigation_start = base::Time::FromDoubleT(10); |  536   timing.navigation_start = base::Time::FromDoubleT(10); | 
|  522  |  537  | 
|  523   content::WebContentsTester* web_contents_tester = |  538   content::WebContentsTester* web_contents_tester = | 
|  524       content::WebContentsTester::For(web_contents()); |  539       content::WebContentsTester::For(web_contents()); | 
|  525   content::RenderFrameHostTester* rfh_tester = |  540   content::RenderFrameHostTester* rfh_tester = | 
|  526       content::RenderFrameHostTester::For(main_rfh()); |  541       content::RenderFrameHostTester::For(main_rfh()); | 
|  527  |  542  | 
|  528   // Start the navigation, then start observing the web contents. This used to |  543   // Start the navigation, then start observing the web contents. This used to | 
|  529   // crash us. Make sure we bail out and don't log histograms. |  544   // crash us. Make sure we bail out and don't log histograms. | 
|  530   web_contents_tester->StartNavigation(GURL(kDefaultTestUrl)); |  545   web_contents_tester->StartNavigation(GURL(kDefaultTestUrl)); | 
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  704             completed_filtered_urls()); |  719             completed_filtered_urls()); | 
|  705  |  720  | 
|  706   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); |  721   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | 
|  707   ASSERT_EQ(std::vector<GURL>({GURL(kDefaultTestUrl), GURL(kDefaultTestUrl2)}), |  722   ASSERT_EQ(std::vector<GURL>({GURL(kDefaultTestUrl), GURL(kDefaultTestUrl2)}), | 
|  708             completed_filtered_urls()); |  723             completed_filtered_urls()); | 
|  709 } |  724 } | 
|  710  |  725  | 
|  711 // We buffer cross frame timings in order to provide a consistent view of |  726 // We buffer cross frame timings in order to provide a consistent view of | 
|  712 // timing data to observers. See crbug.com/722860 for more. |  727 // timing data to observers. See crbug.com/722860 for more. | 
|  713 TEST_F(MetricsWebContentsObserverTest, OutOfOrderCrossFrameTiming) { |  728 TEST_F(MetricsWebContentsObserverTest, OutOfOrderCrossFrameTiming) { | 
|  714   PageLoadTiming timing; |  729   mojom::PageLoadTiming timing; | 
 |  730   page_load_metrics::InitPageLoadTimingForTest(&timing); | 
|  715   timing.navigation_start = base::Time::FromDoubleT(1); |  731   timing.navigation_start = base::Time::FromDoubleT(1); | 
|  716   timing.response_start = base::TimeDelta::FromMilliseconds(10); |  732   timing.response_start = base::TimeDelta::FromMilliseconds(10); | 
|  717  |  733  | 
|  718   content::WebContentsTester* web_contents_tester = |  734   content::WebContentsTester* web_contents_tester = | 
|  719       content::WebContentsTester::For(web_contents()); |  735       content::WebContentsTester::For(web_contents()); | 
|  720   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); |  736   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | 
|  721   SimulateTimingUpdate(timing); |  737   SimulateTimingUpdate(timing); | 
|  722  |  738  | 
|  723   ASSERT_EQ(1, CountUpdatedTimingReported()); |  739   ASSERT_EQ(1, CountUpdatedTimingReported()); | 
|  724   EXPECT_EQ(timing, updated_timings().back()); |  740   EXPECT_TRUE(timing.Equals(*updated_timings().back())); | 
|  725  |  741  | 
|  726   content::RenderFrameHostTester* rfh_tester = |  742   content::RenderFrameHostTester* rfh_tester = | 
|  727       content::RenderFrameHostTester::For(main_rfh()); |  743       content::RenderFrameHostTester::For(main_rfh()); | 
|  728   content::RenderFrameHost* subframe = rfh_tester->AppendChild("subframe"); |  744   content::RenderFrameHost* subframe = rfh_tester->AppendChild("subframe"); | 
|  729  |  745  | 
|  730   // Dispatch a timing update for the child frame that includes a first paint. |  746   // Dispatch a timing update for the child frame that includes a first paint. | 
|  731   PageLoadTiming subframe_timing; |  747   mojom::PageLoadTiming subframe_timing; | 
 |  748   page_load_metrics::InitPageLoadTimingForTest(&subframe_timing); | 
|  732   subframe_timing.navigation_start = base::Time::FromDoubleT(2); |  749   subframe_timing.navigation_start = base::Time::FromDoubleT(2); | 
|  733   subframe_timing.response_start = base::TimeDelta::FromMilliseconds(10); |  750   subframe_timing.response_start = base::TimeDelta::FromMilliseconds(10); | 
|  734   subframe_timing.parse_timing.parse_start = |  751   subframe_timing.parse_timing->parse_start = | 
|  735       base::TimeDelta::FromMilliseconds(20); |  752       base::TimeDelta::FromMilliseconds(20); | 
|  736   subframe_timing.document_timing.first_layout = |  753   subframe_timing.document_timing->first_layout = | 
|  737       base::TimeDelta::FromMilliseconds(30); |  754       base::TimeDelta::FromMilliseconds(30); | 
|  738   subframe_timing.paint_timing.first_paint = |  755   subframe_timing.paint_timing->first_paint = | 
|  739       base::TimeDelta::FromMilliseconds(40); |  756       base::TimeDelta::FromMilliseconds(40); | 
|  740   content::RenderFrameHostTester* subframe_tester = |  757   content::RenderFrameHostTester* subframe_tester = | 
|  741       content::RenderFrameHostTester::For(subframe); |  758       content::RenderFrameHostTester::For(subframe); | 
|  742   subframe_tester->SimulateNavigationStart(GURL(kDefaultTestUrl2)); |  759   subframe_tester->SimulateNavigationStart(GURL(kDefaultTestUrl2)); | 
|  743   subframe_tester->SimulateNavigationCommit(GURL(kDefaultTestUrl2)); |  760   subframe_tester->SimulateNavigationCommit(GURL(kDefaultTestUrl2)); | 
|  744   SimulateTimingUpdate(subframe_timing, subframe); |  761   SimulateTimingUpdate(subframe_timing, subframe); | 
|  745   subframe_tester->SimulateNavigationStop(); |  762   subframe_tester->SimulateNavigationStop(); | 
|  746  |  763  | 
|  747   // Though a first paint was dispatched in the child, it should not yet be |  764   // Though a first paint was dispatched in the child, it should not yet be | 
|  748   // reflected as an updated timing in the main frame, since the main frame |  765   // reflected as an updated timing in the main frame, since the main frame | 
|  749   // hasn't received updates for required earlier events such as parse_start and |  766   // hasn't received updates for required earlier events such as parse_start and | 
|  750   // first_layout. |  767   // first_layout. | 
|  751   ASSERT_EQ(1, CountUpdatedSubFrameTimingReported()); |  768   ASSERT_EQ(1, CountUpdatedSubFrameTimingReported()); | 
|  752   EXPECT_EQ(subframe_timing, updated_subframe_timings().back()); |  769   EXPECT_TRUE(subframe_timing.Equals(*updated_subframe_timings().back())); | 
|  753   ASSERT_EQ(1, CountUpdatedTimingReported()); |  770   ASSERT_EQ(1, CountUpdatedTimingReported()); | 
|  754   EXPECT_EQ(timing, updated_timings().back()); |  771   EXPECT_TRUE(timing.Equals(*updated_timings().back())); | 
|  755  |  772  | 
|  756   // Dispatch the parse_start event in the parent. We should still not observe |  773   // Dispatch the parse_start event in the parent. We should still not observe | 
|  757   // a first paint main frame update, since we don't yet have a first_layout. |  774   // a first paint main frame update, since we don't yet have a first_layout. | 
|  758   timing.parse_timing.parse_start = base::TimeDelta::FromMilliseconds(20); |  775   timing.parse_timing->parse_start = base::TimeDelta::FromMilliseconds(20); | 
|  759   SimulateTimingUpdate(timing); |  776   SimulateTimingUpdate(timing); | 
|  760   ASSERT_EQ(1, CountUpdatedTimingReported()); |  777   ASSERT_EQ(1, CountUpdatedTimingReported()); | 
|  761   EXPECT_NE(timing, updated_timings().back()); |  778   EXPECT_FALSE(timing.Equals(*updated_timings().back())); | 
|  762   EXPECT_FALSE(updated_timings().back().parse_timing.parse_start); |  779   EXPECT_FALSE(updated_timings().back()->parse_timing->parse_start); | 
|  763   EXPECT_FALSE(updated_timings().back().paint_timing.first_paint); |  780   EXPECT_FALSE(updated_timings().back()->paint_timing->first_paint); | 
|  764  |  781  | 
|  765   // Dispatch a first_layout in the parent. We should now unbuffer the first |  782   // Dispatch a first_layout in the parent. We should now unbuffer the first | 
|  766   // paint main frame update and receive a main frame update with a first paint |  783   // paint main frame update and receive a main frame update with a first paint | 
|  767   // value. |  784   // value. | 
|  768   timing.document_timing.first_layout = base::TimeDelta::FromMilliseconds(30); |  785   timing.document_timing->first_layout = base::TimeDelta::FromMilliseconds(30); | 
|  769   SimulateTimingUpdate(timing); |  786   SimulateTimingUpdate(timing); | 
|  770   ASSERT_EQ(2, CountUpdatedTimingReported()); |  787   ASSERT_EQ(2, CountUpdatedTimingReported()); | 
|  771   EXPECT_NE(timing, updated_timings().back()); |  788   EXPECT_FALSE(timing.Equals(*updated_timings().back())); | 
|  772   EXPECT_EQ(updated_timings().back().parse_timing, timing.parse_timing); |  789   EXPECT_TRUE( | 
|  773   EXPECT_EQ(updated_timings().back().document_timing, timing.document_timing); |  790       updated_timings().back()->parse_timing->Equals(*timing.parse_timing)); | 
|  774   EXPECT_NE(updated_timings().back().paint_timing, timing.paint_timing); |  791   EXPECT_TRUE(updated_timings().back()->document_timing->Equals( | 
|  775   EXPECT_TRUE(updated_timings().back().paint_timing.first_paint); |  792       *timing.document_timing)); | 
 |  793   EXPECT_FALSE( | 
 |  794       updated_timings().back()->paint_timing->Equals(*timing.paint_timing)); | 
 |  795   EXPECT_TRUE(updated_timings().back()->paint_timing->first_paint); | 
|  776  |  796  | 
|  777   // Navigate again to see if the timing updated for a subframe message. |  797   // Navigate again to see if the timing updated for a subframe message. | 
|  778   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); |  798   web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); | 
|  779  |  799  | 
|  780   ASSERT_EQ(1, CountCompleteTimingReported()); |  800   ASSERT_EQ(1, CountCompleteTimingReported()); | 
|  781   ASSERT_EQ(2, CountUpdatedTimingReported()); |  801   ASSERT_EQ(2, CountUpdatedTimingReported()); | 
|  782   ASSERT_EQ(0, CountEmptyCompleteTimingReported()); |  802   ASSERT_EQ(0, CountEmptyCompleteTimingReported()); | 
|  783  |  803  | 
|  784   ASSERT_EQ(1, CountUpdatedSubFrameTimingReported()); |  804   ASSERT_EQ(1, CountUpdatedSubFrameTimingReported()); | 
|  785   EXPECT_EQ(subframe_timing, updated_subframe_timings().back()); |  805   EXPECT_TRUE(subframe_timing.Equals(*updated_subframe_timings().back())); | 
|  786  |  806  | 
|  787   CheckNoErrorEvents(); |  807   CheckNoErrorEvents(); | 
|  788 } |  808 } | 
|  789  |  809  | 
|  790 }  // namespace page_load_metrics |  810 }  // namespace page_load_metrics | 
| OLD | NEW |