• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4 
5 #include <memory>
6 
7 #include "include/base/cef_callback.h"
8 #include "include/wrapper/cef_closure_task.h"
9 #include "include/wrapper/cef_stream_resource_handler.h"
10 #include "tests/ceftests/test_handler.h"
11 #include "tests/ceftests/test_util.h"
12 #include "tests/gtest/include/gtest/gtest.h"
13 #include "tests/shared/browser/client_app_browser.h"
14 #include "tests/shared/renderer/client_app_renderer.h"
15 
16 using client::ClientAppBrowser;
17 using client::ClientAppRenderer;
18 
19 namespace {
20 
21 // The frame navigation test harness work as follows:
22 //
23 // In the browser process:
24 // 1. TEST() function creates a new FrameNavTestHandler instance with a unique
25 //    FrameNavFactoryId.
26 // 2. FrameNavTestHandler calls FrameNavExpectationsFactoryBrowser::FromID to
27 //    create a new factory instance.
28 // 3. FrameNavTestHandler calls FrameNavExpectationsFactoryBrowser::Create to
29 //    create a new FrameNavExpectationsBrowser instance for the current
30 //    navigation.
31 // 4. FrameNavTestHandler retrieves the URL to load via
32 //    FrameNavExpectationsBrowser::GetMainURL and calls either CreateBrowser
33 //    (for the first navigation) or LoadURL (for the following navigations).
34 // 5. If the renderer process does not already exist CEF creates it with
35 //    command-line arguments that specify the FrameNavFactoryId via
36 //    FrameNavBrowserTest::OnBeforeChildProcessLaunch.
37 //
38 // In the renderer process:
39 // 6. If the renderer process is newly created FrameNavRendererTest calls
40 //    FrameNavExpectationsFactoryRenderer::FromID to create a new factory
41 //    instance.
42 // 7. FrameNavRendererTest calls FrameNavExpectationsFactoryRenderer::Create to
43 //    create a new FrameNavExpectationsRenderer instance for the current
44 //    navigation.
45 //
46 // In both processes:
47 // 8. Callback notifications are sent to the FrameNavExpectations* instances.
48 //
49 // In the renderer process:
50 // 9. When the FrameNavExpectationsRenderer instance determines that the
51 //    renderer side of the test is complete it calls SignalComplete which
52 //    finalizes and deletes the FrameNavExpectationsRenderer instance and
53 //    sends an IPC message to the browser process.
54 //
55 // In the browser process:
56 // 11.FrameNavExpectationsBrowser::OnRendererComplete is called in response to
57 //    renderer-side test completion message.
58 // 12.When the FrameNavExpectationsBrowser instance determines that the browser
59 //    side of the test is complete it calls SignalComplete which finalizes and
60 //    deletes the FrameNavExpectationsBrowser instance.
61 // 13.If FrameNavExpectationsFactoryBrowser::HasMoreNavigations returns false
62 //    then DestroyTest is called and the test ends. Otherwise, the navigation
63 //    count is incremented and the process repeats starting with step #3.
64 //
65 //
66 // To add a new test case:
67 // 1. Add a new value to the FrameNavFactoryId enumeration.
68 // 2. Provide implementations of FrameNavExpectations*.
69 // 3. Add a case for the new factory ID to FrameNavExpectationsFactory*::FromID.
70 // 4. Implement a TEST() function that creates a FrameNavTestHandler instance
71 //    and passes the new factory ID.
72 //
73 //
74 // Run with the `--single-process` command-line flag to see expectation failures
75 // from the renderer process.
76 //
77 
78 // All known factory IDs.
79 enum FrameNavFactoryId {
80   FNF_ID_INVALID = 0,
81   FNF_ID_SINGLE_NAV_HARNESS,
82   FNF_ID_SINGLE_NAV,
83   FNF_ID_MULTI_NAV_HARNESS,
84   FNF_ID_MULTI_NAV,
85   FNF_ID_NESTED_IFRAMES_SAME_ORIGIN,
86   FNF_ID_NESTED_IFRAMES_DIFF_ORIGIN,
87 };
88 
89 // IPC message name.
90 const char kFrameNavMsg[] = "FrameTest.Navigation";
91 
92 // Extra info parameter keys.
93 const char kFrameNavTestCmdKey[] = "frame-nav-test";
94 
95 // Origins used in tests.
96 const char kFrameNavOrigin0[] = "http://tests-framenav0.com/";
97 const char kFrameNavOrigin1[] = "http://tests-framenav1.com/";
98 const char kFrameNavOrigin2[] = "http://tests-framenav2.com/";
99 const char kFrameNavOrigin3[] = "http://tests-framenav3.com/";
100 
101 // Maximum number of navigations. Should be kept synchronized with the number
102 // of kFrameNavOrigin* values. Don't modify this value without checking the
103 // below use cases.
104 const int kMaxMultiNavNavigations = 4;
105 
106 // Abstract base class representing expectations that result from a navigation.
107 class FrameNavExpectations {
108  public:
109   typedef base::OnceCallback<void(CefRefPtr<CefBrowser>, CefRefPtr<CefFrame>)>
110       CompletionCallback;
111 
FrameNavExpectations(int nav,bool renderer)112   FrameNavExpectations(int nav, bool renderer)
113       : nav_(nav), renderer_(renderer) {}
~FrameNavExpectations()114   virtual ~FrameNavExpectations() {}
115 
116   // Browser and renderer notifications.
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading)117   virtual bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
118                                     bool isLoading) {
119     return true;
120   }
OnLoadStart(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)121   virtual bool OnLoadStart(CefRefPtr<CefBrowser> browser,
122                            CefRefPtr<CefFrame> frame) {
123     return true;
124   }
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)125   virtual bool OnLoadEnd(CefRefPtr<CefBrowser> browser,
126                          CefRefPtr<CefFrame> frame) {
127     return true;
128   }
129 
130   // Final expectations check before this object is deleted.
131   virtual bool Finalize() = 0;
132 
133   // Signal that all expectations are completed. Should be called as a result of
134   // notifications.
SignalComplete(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)135   void SignalComplete(CefRefPtr<CefBrowser> browser,
136                       CefRefPtr<CefFrame> frame) {
137     if (!completion_callback_.is_null()) {
138       // Execute the callback asynchronously to avoid any issues with what's
139       // currently on the stack.
140       CefPostTask(
141           (renderer_ ? TID_RENDERER : TID_UI),
142           base::BindOnce(std::move(completion_callback_), browser, frame));
143     }
144   }
145 
146   // Returns the current navigation count. In the browser process this value
147   // increments over the life span of the FrameNavTestHandler instance. In the
148   // renderer process this value increments over the life span of a single
149   // renderer instance (i.e. cross-origin navigations will cause this value to
150   // reset).
nav() const151   int nav() const { return nav_; }
152 
153   // Returns true if this is a renderer-side expectation object.
renderer() const154   bool renderer() const { return renderer_; }
155 
set_completion_callback(CompletionCallback completion_callback)156   void set_completion_callback(CompletionCallback completion_callback) {
157     completion_callback_ = std::move(completion_callback);
158   }
159 
160  private:
161   int nav_;
162   bool renderer_;
163   CompletionCallback completion_callback_;
164 };
165 
166 // Browser process expectations abstract base class.
167 class FrameNavExpectationsBrowser : public FrameNavExpectations {
168  public:
FrameNavExpectationsBrowser(int nav)169   explicit FrameNavExpectationsBrowser(int nav)
170       : FrameNavExpectations(nav, false) {}
171 
172   // Loading information.
173   virtual std::string GetMainURL() = 0;
174   virtual std::string GetContentForURL(const std::string& url) = 0;
175 
176   // Browser-only notifications.
OnAfterCreated(CefRefPtr<CefBrowser> browser)177   virtual bool OnAfterCreated(CefRefPtr<CefBrowser> browser) {
178     EXPECT_TRUE(browser.get());
179     return true;
180   }
OnBeforeBrowse(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & url)181   virtual bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
182                               CefRefPtr<CefFrame> frame,
183                               const std::string& url) {
184     EXPECT_TRUE(browser.get());
185     EXPECT_TRUE(frame.get());
186     EXPECT_FALSE(url.empty());
187     return true;
188   }
GetResourceHandler(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)189   virtual bool GetResourceHandler(CefRefPtr<CefBrowser> browser,
190                                   CefRefPtr<CefFrame> frame) {
191     EXPECT_TRUE(browser.get());
192     EXPECT_TRUE(frame.get());
193     return true;
194   }
195 
196   // Called when the renderer signals completion.
197   virtual bool OnRendererComplete(CefRefPtr<CefBrowser> browser,
198                                   CefRefPtr<CefFrame> frame,
199                                   int renderer_nav,
200                                   bool renderer_result) = 0;
201 };
202 
203 // Renderer process expectations abstract base class.
204 class FrameNavExpectationsRenderer : public FrameNavExpectations {
205  public:
FrameNavExpectationsRenderer(int nav)206   explicit FrameNavExpectationsRenderer(int nav)
207       : FrameNavExpectations(nav, true) {}
208 };
209 
210 // Abstract base class for the factory that creates expectations objects.
211 class FrameNavExpectationsFactory {
212  public:
FrameNavExpectationsFactory()213   FrameNavExpectationsFactory() {}
~FrameNavExpectationsFactory()214   virtual ~FrameNavExpectationsFactory() {}
215 
216   // Returns the unique ID for this factory type.
217   virtual FrameNavFactoryId GetID() const = 0;
218 };
219 
220 // Browser process expectations factory abstact base class.
221 class FrameNavExpectationsFactoryBrowser : public FrameNavExpectationsFactory {
222  public:
FrameNavExpectationsFactoryBrowser()223   FrameNavExpectationsFactoryBrowser() {}
224 
225   // Create a new factory instance of the specified type.
226   static std::unique_ptr<FrameNavExpectationsFactoryBrowser> FromID(
227       FrameNavFactoryId id);
228 
229   // Returns true if there will be more navigations in the browser process
230   // handler.
231   virtual bool HasMoreNavigations() const = 0;
232 
233   // Verify final expectations results.
234   virtual bool Finalize() = 0;
235 
Create(int nav,FrameNavExpectations::CompletionCallback completion_callback)236   std::unique_ptr<FrameNavExpectationsBrowser> Create(
237       int nav,
238       FrameNavExpectations::CompletionCallback completion_callback) {
239     auto expectations = Create(nav);
240     expectations->set_completion_callback(std::move(completion_callback));
241     return expectations;
242   }
243 
244  protected:
245   // Implement in the test-specific factory instance.
246   virtual std::unique_ptr<FrameNavExpectationsBrowser> Create(int nav) = 0;
247 };
248 
249 // Renderer process expectations factory abstact base class.
250 class FrameNavExpectationsFactoryRenderer : public FrameNavExpectationsFactory {
251  public:
FrameNavExpectationsFactoryRenderer()252   FrameNavExpectationsFactoryRenderer() {}
253 
254   // Create a new factory instance of the specified type.
255   static std::unique_ptr<FrameNavExpectationsFactoryRenderer> FromID(
256       FrameNavFactoryId id);
257 
Create(int nav,FrameNavExpectations::CompletionCallback completion_callback)258   std::unique_ptr<FrameNavExpectationsRenderer> Create(
259       int nav,
260       FrameNavExpectations::CompletionCallback completion_callback) {
261     auto expectations = Create(nav);
262     expectations->set_completion_callback(std::move(completion_callback));
263     return expectations;
264   }
265 
266  protected:
267   // Implement in the test-specific factory instance.
268   virtual std::unique_ptr<FrameNavExpectationsRenderer> Create(int nav) = 0;
269 };
270 
271 // Renderer side handler.
272 class FrameNavRendererTest : public ClientAppRenderer::Delegate,
273                              public CefLoadHandler {
274  public:
FrameNavRendererTest()275   FrameNavRendererTest() : run_test_(false), nav_(0) {}
276 
OnBrowserCreated(CefRefPtr<ClientAppRenderer> app,CefRefPtr<CefBrowser> browser,CefRefPtr<CefDictionaryValue> extra_info)277   void OnBrowserCreated(CefRefPtr<ClientAppRenderer> app,
278                         CefRefPtr<CefBrowser> browser,
279                         CefRefPtr<CefDictionaryValue> extra_info) override {
280     if (!extra_info || !extra_info->HasKey(kFrameNavTestCmdKey))
281       return;
282 
283     FrameNavFactoryId factory_id =
284         static_cast<FrameNavFactoryId>(extra_info->GetInt(kFrameNavTestCmdKey));
285     run_test_ = factory_id != FNF_ID_INVALID;
286     if (!run_test_)
287       return;
288 
289     factory_ = FrameNavExpectationsFactoryRenderer::FromID(factory_id);
290   }
291 
GetLoadHandler(CefRefPtr<ClientAppRenderer> app)292   CefRefPtr<CefLoadHandler> GetLoadHandler(
293       CefRefPtr<ClientAppRenderer> app) override {
294     if (!run_test_)
295       return nullptr;
296 
297     return this;
298   }
299 
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading,bool canGoBack,bool canGoForward)300   void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
301                             bool isLoading,
302                             bool canGoBack,
303                             bool canGoForward) override {
304     CreateExpectationsIfNecessary();
305     EXPECT_TRUE(expectations_->OnLoadingStateChange(browser, isLoading))
306         << "isLoading = " << isLoading << ", nav = " << nav_;
307   }
308 
OnLoadStart(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,TransitionType transition_type)309   void OnLoadStart(CefRefPtr<CefBrowser> browser,
310                    CefRefPtr<CefFrame> frame,
311                    TransitionType transition_type) override {
312     CreateExpectationsIfNecessary();
313     EXPECT_TRUE(expectations_->OnLoadStart(browser, frame)) << "nav = " << nav_;
314   }
315 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int httpStatusCode)316   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
317                  CefRefPtr<CefFrame> frame,
318                  int httpStatusCode) override {
319     CreateExpectationsIfNecessary();
320     EXPECT_TRUE(expectations_->OnLoadEnd(browser, frame)) << "nav = " << nav_;
321   }
322 
323  protected:
324   // Create a new expectations object if one does not already exist for the
325   // current navigation.
CreateExpectationsIfNecessary()326   void CreateExpectationsIfNecessary() {
327     if (expectations_)
328       return;
329     expectations_ = factory_->Create(
330         nav_, base::BindOnce(&FrameNavRendererTest::SendTestResults, this));
331   }
332 
333   // Send the test results.
334   // Will be called via FrameNavExpectations::SignalComplete.
SendTestResults(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)335   void SendTestResults(CefRefPtr<CefBrowser> browser,
336                        CefRefPtr<CefFrame> frame) {
337     // End of the current expectations object.
338     EXPECT_TRUE(expectations_->Finalize()) << "nav = " << nav_;
339     expectations_.reset(nullptr);
340 
341     // Check if the test has failed.
342     bool result = !TestFailed();
343 
344     // Return the result to the browser process.
345     CefRefPtr<CefProcessMessage> return_msg =
346         CefProcessMessage::Create(kFrameNavMsg);
347     CefRefPtr<CefListValue> args = return_msg->GetArgumentList();
348     EXPECT_TRUE(args.get());
349     EXPECT_TRUE(args->SetInt(0, nav_));
350     EXPECT_TRUE(args->SetBool(1, result));
351 
352     const int64 frame_id = frame->GetIdentifier();
353     EXPECT_TRUE(args->SetInt(2, CefInt64GetLow(frame_id)));
354     EXPECT_TRUE(args->SetInt(3, CefInt64GetHigh(frame_id)));
355 
356     frame->SendProcessMessage(PID_BROWSER, return_msg);
357 
358     nav_++;
359   }
360 
361   bool run_test_;
362   int nav_;
363   std::unique_ptr<FrameNavExpectationsFactoryRenderer> factory_;
364   std::unique_ptr<FrameNavExpectationsRenderer> expectations_;
365 
366   IMPLEMENT_REFCOUNTING(FrameNavRendererTest);
367 };
368 
369 // Browser side handler.
370 class FrameNavTestHandler : public TestHandler {
371  public:
FrameNavTestHandler(FrameNavFactoryId factory_id)372   explicit FrameNavTestHandler(FrameNavFactoryId factory_id)
373       : nav_(0),
374         factory_(FrameNavExpectationsFactoryBrowser::FromID(factory_id)) {}
375 
~FrameNavTestHandler()376   ~FrameNavTestHandler() override { EXPECT_TRUE(got_destroyed_); }
377 
RunTest()378   void RunTest() override {
379     // Create the first expectations object.
380     expectations_ = factory_->Create(
381         nav_, base::BindOnce(&FrameNavTestHandler::RunNextNav, this));
382 
383     CefRefPtr<CefDictionaryValue> extra_info = CefDictionaryValue::Create();
384     extra_info->SetInt(kFrameNavTestCmdKey, factory_->GetID());
385 
386     // Create the browser with the initial URL.
387     CreateBrowser(expectations_->GetMainURL(), nullptr, extra_info);
388 
389     // Time out the test after a reasonable period of time.
390     SetTestTimeout(15000);
391   }
392 
393   // Transition to the next navigation.
394   // Will be called via FrameNavExpectations::SignalComplete.
RunNextNav(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)395   void RunNextNav(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame) {
396     // End of the current expectations object.
397     EXPECT_TRUE(expectations_->Finalize());
398     expectations_.reset(nullptr);
399 
400     if (!factory_->HasMoreNavigations()) {
401       // End of the test.
402       DestroyTest();
403       return;
404     }
405 
406     nav_++;
407 
408     // Create the next expectations object.
409     expectations_ = factory_->Create(
410         nav_, base::BindOnce(&FrameNavTestHandler::RunNextNav, this));
411 
412     // Load the main URL.
413     browser->GetMainFrame()->LoadURL(expectations_->GetMainURL());
414   }
415 
OnAfterCreated(CefRefPtr<CefBrowser> browser)416   void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
417     TestHandler::OnAfterCreated(browser);
418 
419     EXPECT_TRUE(expectations_->OnAfterCreated(browser)) << "nav = " << nav_;
420   }
421 
GetResourceHandler(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request)422   CefRefPtr<CefResourceHandler> GetResourceHandler(
423       CefRefPtr<CefBrowser> browser,
424       CefRefPtr<CefFrame> frame,
425       CefRefPtr<CefRequest> request) override {
426     const std::string& url = request->GetURL();
427     if (IgnoreURL(url))
428       return nullptr;
429 
430     EXPECT_TRUE(expectations_->GetResourceHandler(browser, frame))
431         << "nav = " << nav_;
432 
433     const std::string& content = expectations_->GetContentForURL(url);
434     EXPECT_TRUE(!content.empty()) << "nav = " << nav_;
435 
436     CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData(
437         static_cast<void*>(const_cast<char*>(content.c_str())),
438         content.length());
439     return new CefStreamResourceHandler("text/html", stream);
440   }
441 
OnBeforeBrowse(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,bool user_gesture,bool is_redirect)442   bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
443                       CefRefPtr<CefFrame> frame,
444                       CefRefPtr<CefRequest> request,
445                       bool user_gesture,
446                       bool is_redirect) override {
447     EXPECT_TRUE(
448         expectations_->OnBeforeBrowse(browser, frame, request->GetURL()))
449         << "nav = " << nav_;
450 
451     return false;
452   }
453 
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading,bool canGoBack,bool canGoForward)454   void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
455                             bool isLoading,
456                             bool canGoBack,
457                             bool canGoForward) override {
458     EXPECT_TRUE(expectations_->OnLoadingStateChange(browser, isLoading))
459         << "isLoading = " << isLoading << ", nav = " << nav_;
460     ;
461   }
462 
OnLoadStart(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,TransitionType transition_type)463   void OnLoadStart(CefRefPtr<CefBrowser> browser,
464                    CefRefPtr<CefFrame> frame,
465                    TransitionType transition_type) override {
466     EXPECT_TRUE(expectations_->OnLoadStart(browser, frame)) << "nav = " << nav_;
467   }
468 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int httpStatusCode)469   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
470                  CefRefPtr<CefFrame> frame,
471                  int httpStatusCode) override {
472     EXPECT_TRUE(expectations_->OnLoadEnd(browser, frame)) << "nav = " << nav_;
473   }
474 
OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefProcessId source_process,CefRefPtr<CefProcessMessage> message)475   bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
476                                 CefRefPtr<CefFrame> frame,
477                                 CefProcessId source_process,
478                                 CefRefPtr<CefProcessMessage> message) override {
479     if (message->GetName().ToString() == kFrameNavMsg) {
480       // Test that the renderer side succeeded.
481       CefRefPtr<CefListValue> args = message->GetArgumentList();
482       EXPECT_TRUE(args.get());
483 
484       EXPECT_TRUE(expectations_->OnRendererComplete(
485           browser, frame, args->GetInt(0), args->GetBool(1)))
486           << "nav = " << nav_;
487 
488       // Test that browser and render process frame IDs match.
489       const int64 frame_id = CefInt64Set(args->GetInt(2), args->GetInt(3));
490       EXPECT_EQ(frame->GetIdentifier(), frame_id);
491 
492       return true;
493     }
494 
495     // Message not handled.
496     return false;
497   }
498 
DestroyTest()499   void DestroyTest() override {
500     if (got_destroyed_)
501       return;
502 
503     got_destroyed_.yes();
504 
505     // The expectations should have been tested already.
506     EXPECT_FALSE(expectations_.get());
507 
508     // Test that factory conditions we met.
509     EXPECT_TRUE(factory_->Finalize()) << "nav = " << nav_;
510 
511     TestHandler::DestroyTest();
512   }
513 
514   int nav_;
515   TrackCallback got_destroyed_;
516   std::unique_ptr<FrameNavExpectationsFactoryBrowser> factory_;
517   std::unique_ptr<FrameNavExpectationsBrowser> expectations_;
518 
519   IMPLEMENT_REFCOUNTING(FrameNavTestHandler);
520 };
521 
522 // Helper for defining frame tests.
523 #define FRAME_TEST(name, factory_id)         \
524   TEST(FrameTest, name) {                    \
525     CefRefPtr<FrameNavTestHandler> handler = \
526         new FrameNavTestHandler(factory_id); \
527     handler->ExecuteTest();                  \
528     ReleaseAndWaitForDestructor(handler);    \
529   }
530 
531 // Browser process expectations for a single navigation.
532 class FrameNavExpectationsBrowserSingleNav
533     : public FrameNavExpectationsBrowser {
534  public:
FrameNavExpectationsBrowserSingleNav(int nav)535   explicit FrameNavExpectationsBrowserSingleNav(int nav)
536       : FrameNavExpectationsBrowser(nav) {}
537 
~FrameNavExpectationsBrowserSingleNav()538   ~FrameNavExpectationsBrowserSingleNav() override {
539     EXPECT_TRUE(got_finalize_);
540   }
541 
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading)542   bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
543                             bool isLoading) override {
544     if (isLoading) {
545       EXPECT_FALSE(got_loading_state_change_start_);
546       got_loading_state_change_start_.yes();
547     } else {
548       EXPECT_FALSE(got_loading_state_change_end_);
549       got_loading_state_change_end_.yes();
550       SignalCompleteIfDone(browser, browser->GetMainFrame());
551     }
552     return true;
553   }
554 
OnLoadStart(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)555   bool OnLoadStart(CefRefPtr<CefBrowser> browser,
556                    CefRefPtr<CefFrame> frame) override {
557     EXPECT_FALSE(got_load_start_);
558     got_load_start_.yes();
559     return true;
560   }
561 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)562   bool OnLoadEnd(CefRefPtr<CefBrowser> browser,
563                  CefRefPtr<CefFrame> frame) override {
564     EXPECT_FALSE(got_load_end_);
565     got_load_end_.yes();
566     SignalCompleteIfDone(browser, frame);
567     return true;
568   }
569 
OnAfterCreated(CefRefPtr<CefBrowser> browser)570   bool OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
571     EXPECT_FALSE(got_after_created_);
572     got_after_created_.yes();
573     return true;
574   }
575 
OnBeforeBrowse(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & url)576   bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
577                       CefRefPtr<CefFrame> frame,
578                       const std::string& url) override {
579     EXPECT_FALSE(got_before_browse_);
580     got_before_browse_.yes();
581     return true;
582   }
583 
GetResourceHandler(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)584   bool GetResourceHandler(CefRefPtr<CefBrowser> browser,
585                           CefRefPtr<CefFrame> frame) override {
586     EXPECT_FALSE(got_get_resource_handler_);
587     got_get_resource_handler_.yes();
588     return true;
589   }
590 
OnRendererComplete(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int renderer_nav,bool renderer_result)591   bool OnRendererComplete(CefRefPtr<CefBrowser> browser,
592                           CefRefPtr<CefFrame> frame,
593                           int renderer_nav,
594                           bool renderer_result) override {
595     EXPECT_EQ(nav(), renderer_nav);
596     EXPECT_TRUE(renderer_result);
597     EXPECT_FALSE(got_renderer_done_);
598     got_renderer_done_.yes();
599     SignalCompleteIfDone(browser, frame);
600     return true;
601   }
602 
Finalize()603   bool Finalize() override {
604     V_DECLARE();
605     V_EXPECT_TRUE(got_load_start_);
606     V_EXPECT_TRUE(got_load_end_);
607     V_EXPECT_TRUE(got_loading_state_change_start_);
608     V_EXPECT_TRUE(got_loading_state_change_end_);
609     V_EXPECT_TRUE(got_renderer_done_);
610     V_EXPECT_TRUE(got_after_created_);
611     V_EXPECT_TRUE(got_before_browse_);
612     V_EXPECT_TRUE(got_get_resource_handler_);
613     V_EXPECT_FALSE(got_finalize_);
614 
615     got_finalize_.yes();
616 
617     V_RETURN();
618   }
619 
620  private:
SignalCompleteIfDone(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)621   void SignalCompleteIfDone(CefRefPtr<CefBrowser> browser,
622                             CefRefPtr<CefFrame> frame) {
623     if (got_renderer_done_ && got_load_end_ && got_loading_state_change_end_)
624       SignalComplete(browser, frame);
625   }
626 
627   TrackCallback got_load_start_;
628   TrackCallback got_load_end_;
629   TrackCallback got_loading_state_change_start_;
630   TrackCallback got_loading_state_change_end_;
631   TrackCallback got_renderer_done_;
632   TrackCallback got_after_created_;
633   TrackCallback got_before_browse_;
634   TrackCallback got_get_resource_handler_;
635   TrackCallback got_finalize_;
636 };
637 
638 // Renderer process expectations for a single navigation.
639 class FrameNavExpectationsRendererSingleNav
640     : public FrameNavExpectationsRenderer {
641  public:
FrameNavExpectationsRendererSingleNav(int nav)642   explicit FrameNavExpectationsRendererSingleNav(int nav)
643       : FrameNavExpectationsRenderer(nav) {}
644 
~FrameNavExpectationsRendererSingleNav()645   ~FrameNavExpectationsRendererSingleNav() override {
646     EXPECT_TRUE(got_finalize_);
647   }
648 
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading)649   bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
650                             bool isLoading) override {
651     if (isLoading) {
652       EXPECT_FALSE(got_loading_state_change_start_);
653       got_loading_state_change_start_.yes();
654     } else {
655       EXPECT_FALSE(got_loading_state_change_end_);
656       got_loading_state_change_end_.yes();
657       SignalCompleteIfDone(browser, browser->GetMainFrame());
658     }
659     return true;
660   }
661 
OnLoadStart(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)662   bool OnLoadStart(CefRefPtr<CefBrowser> browser,
663                    CefRefPtr<CefFrame> frame) override {
664     EXPECT_FALSE(got_load_start_);
665     got_load_start_.yes();
666     return true;
667   }
668 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)669   bool OnLoadEnd(CefRefPtr<CefBrowser> browser,
670                  CefRefPtr<CefFrame> frame) override {
671     EXPECT_FALSE(got_load_end_);
672     got_load_end_.yes();
673     SignalCompleteIfDone(browser, frame);
674     return true;
675   }
676 
Finalize()677   bool Finalize() override {
678     V_DECLARE();
679     V_EXPECT_TRUE(got_load_start_);
680     V_EXPECT_TRUE(got_load_end_);
681     V_EXPECT_TRUE(got_loading_state_change_start_);
682     V_EXPECT_TRUE(got_loading_state_change_end_);
683     V_EXPECT_FALSE(got_finalize_);
684 
685     got_finalize_.yes();
686 
687     V_RETURN();
688   }
689 
690  private:
SignalCompleteIfDone(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)691   void SignalCompleteIfDone(CefRefPtr<CefBrowser> browser,
692                             CefRefPtr<CefFrame> frame) {
693     if (got_load_end_ && got_loading_state_change_end_)
694       SignalComplete(browser, frame);
695   }
696 
697   TrackCallback got_load_start_;
698   TrackCallback got_load_end_;
699   TrackCallback got_loading_state_change_start_;
700   TrackCallback got_loading_state_change_end_;
701   TrackCallback got_finalize_;
702 };
703 
704 // Test that the single nav harness works.
705 class FrameNavExpectationsBrowserTestSingleNavHarness
706     : public FrameNavExpectationsBrowserSingleNav {
707  public:
708   typedef FrameNavExpectationsBrowserSingleNav parent;
709 
FrameNavExpectationsBrowserTestSingleNavHarness(int nav)710   explicit FrameNavExpectationsBrowserTestSingleNavHarness(int nav)
711       : parent(nav) {}
712 
~FrameNavExpectationsBrowserTestSingleNavHarness()713   ~FrameNavExpectationsBrowserTestSingleNavHarness() override {
714     EXPECT_TRUE(got_finalize_);
715   }
716 
GetMainURL()717   std::string GetMainURL() override {
718     EXPECT_FALSE(got_get_main_url_);
719     got_get_main_url_.yes();
720     return kFrameNavOrigin0;
721   }
722 
GetContentForURL(const std::string & url)723   std::string GetContentForURL(const std::string& url) override {
724     EXPECT_FALSE(got_get_content_for_url_);
725     got_get_content_for_url_.yes();
726     EXPECT_STREQ(kFrameNavOrigin0, url.c_str());
727     return "<html><body>Nav</body></html>";
728   }
729 
Finalize()730   bool Finalize() override {
731     EXPECT_FALSE(got_finalize_);
732     got_finalize_.yes();
733 
734     V_DECLARE();
735     V_EXPECT_TRUE(got_get_main_url_);
736     V_EXPECT_TRUE(got_get_content_for_url_);
737     V_EXPECT_TRUE(parent::Finalize());
738     V_RETURN();
739   }
740 
741  private:
742   TrackCallback got_get_main_url_;
743   TrackCallback got_get_content_for_url_;
744   TrackCallback got_finalize_;
745 };
746 
747 class FrameNavExpectationsRendererTestSingleNavHarness
748     : public FrameNavExpectationsRendererSingleNav {
749  public:
750   typedef FrameNavExpectationsRendererSingleNav parent;
751 
FrameNavExpectationsRendererTestSingleNavHarness(int nav)752   explicit FrameNavExpectationsRendererTestSingleNavHarness(int nav)
753       : parent(nav) {}
754 
~FrameNavExpectationsRendererTestSingleNavHarness()755   ~FrameNavExpectationsRendererTestSingleNavHarness() override {
756     EXPECT_TRUE(got_finalize_);
757   }
758 
Finalize()759   bool Finalize() override {
760     EXPECT_FALSE(got_finalize_);
761     got_finalize_.yes();
762     return parent::Finalize();
763   }
764 
765  private:
766   TrackCallback got_finalize_;
767 };
768 
769 class FrameNavExpectationsFactoryBrowserTestSingleNavHarness
770     : public FrameNavExpectationsFactoryBrowser {
771  public:
FrameNavExpectationsFactoryBrowserTestSingleNavHarness()772   FrameNavExpectationsFactoryBrowserTestSingleNavHarness() {}
773 
~FrameNavExpectationsFactoryBrowserTestSingleNavHarness()774   ~FrameNavExpectationsFactoryBrowserTestSingleNavHarness() override {
775     EXPECT_TRUE(got_finalize_);
776   }
777 
GetID() const778   FrameNavFactoryId GetID() const override { return FNF_ID_SINGLE_NAV_HARNESS; }
779 
HasMoreNavigations() const780   bool HasMoreNavigations() const override {
781     EXPECT_FALSE(got_get_browser_navigation_count_);
782     got_get_browser_navigation_count_.yes();
783     return false;
784   }
785 
Finalize()786   bool Finalize() override {
787     EXPECT_FALSE(got_finalize_);
788     got_finalize_.yes();
789 
790     V_DECLARE();
791     V_EXPECT_TRUE(got_get_browser_navigation_count_);
792     V_EXPECT_TRUE(got_create_);
793     V_RETURN();
794   }
795 
796  protected:
Create(int nav)797   std::unique_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
798     EXPECT_FALSE(got_create_);
799     got_create_.yes();
800     return std::make_unique<FrameNavExpectationsBrowserTestSingleNavHarness>(
801         nav);
802   }
803 
804  private:
805   mutable TrackCallback got_get_browser_navigation_count_;
806   TrackCallback got_create_;
807   TrackCallback got_finalize_;
808 };
809 
810 class FrameNavExpectationsFactoryRendererTestSingleNavHarness
811     : public FrameNavExpectationsFactoryRenderer {
812  public:
FrameNavExpectationsFactoryRendererTestSingleNavHarness()813   FrameNavExpectationsFactoryRendererTestSingleNavHarness() {}
814 
GetID() const815   FrameNavFactoryId GetID() const override { return FNF_ID_SINGLE_NAV_HARNESS; }
816 
817  protected:
Create(int nav)818   std::unique_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
819     return std::make_unique<FrameNavExpectationsRendererTestSingleNavHarness>(
820         nav);
821   }
822 };
823 
824 }  // namespace
825 
826 // Test that the single nav harness works.
827 FRAME_TEST(SingleNavHarness, FNF_ID_SINGLE_NAV_HARNESS)
828 
829 namespace {
830 
VerifySingleBrowserFrame(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & expected_url)831 bool VerifySingleBrowserFrame(CefRefPtr<CefBrowser> browser,
832                               CefRefPtr<CefFrame> frame,
833                               const std::string& expected_url) {
834   V_DECLARE();
835   V_EXPECT_TRUE(frame.get());
836   V_EXPECT_TRUE(frame->IsValid());
837   const int64 frame_id = frame->GetIdentifier();
838   V_EXPECT_TRUE(frame_id > 0) << frame_id;
839   V_EXPECT_TRUE(frame->IsValid());
840   V_EXPECT_TRUE(frame->IsMain());
841   V_EXPECT_TRUE(frame->IsFocused());
842   V_EXPECT_FALSE(frame->GetParent().get());
843   V_EXPECT_TRUE(frame->GetName().empty());
844   V_EXPECT_TRUE(browser->GetIdentifier() ==
845                 frame->GetBrowser()->GetIdentifier());
846 
847   const std::string& frame_url = frame->GetURL();
848   V_EXPECT_TRUE(frame_url == expected_url)
849       << "frame_url = " << frame_url << ", expected_url = " << expected_url;
850 
851   V_RETURN();
852 }
853 
VerifySingleBrowserFrames(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & expected_url)854 bool VerifySingleBrowserFrames(CefRefPtr<CefBrowser> browser,
855                                CefRefPtr<CefFrame> frame,
856                                const std::string& expected_url) {
857   V_DECLARE();
858   V_EXPECT_TRUE(browser.get());
859 
860   // |frame| may be nullptr for callbacks that don't specify one.
861   if (frame.get()) {
862     V_EXPECT_TRUE(VerifySingleBrowserFrame(browser, frame, expected_url));
863   }
864 
865   CefRefPtr<CefFrame> main_frame = browser->GetMainFrame();
866   V_EXPECT_TRUE(VerifySingleBrowserFrame(browser, main_frame, expected_url));
867 
868   CefRefPtr<CefFrame> focused_frame = browser->GetFocusedFrame();
869   V_EXPECT_TRUE(VerifySingleBrowserFrame(browser, focused_frame, expected_url));
870 
871   size_t frame_count = browser->GetFrameCount();
872   V_EXPECT_TRUE(frame_count == 1U);
873 
874   std::vector<int64> identifiers;
875   browser->GetFrameIdentifiers(identifiers);
876   V_EXPECT_TRUE(identifiers.size() == 1U);
877   if (identifiers.size() == 1U) {
878     V_EXPECT_TRUE(identifiers[0] == main_frame->GetIdentifier());
879     V_EXPECT_TRUE(identifiers[0] == focused_frame->GetIdentifier());
880   }
881 
882   // Names may be empty for callbacks that execute while the frame is loading.
883   std::vector<CefString> names;
884   browser->GetFrameNames(names);
885   V_EXPECT_TRUE(names.size() <= 1U);
886   if (names.size() == 1U) {
887     V_EXPECT_TRUE(names[0].ToString() == main_frame->GetName().ToString());
888     V_EXPECT_TRUE(names[0].ToString() == focused_frame->GetName().ToString());
889   }
890 
891   V_RETURN();
892 }
893 
894 // Test that single navigation works.
895 class FrameNavExpectationsBrowserTestSingleNav
896     : public FrameNavExpectationsBrowserSingleNav {
897  public:
898   typedef FrameNavExpectationsBrowserSingleNav parent;
899 
FrameNavExpectationsBrowserTestSingleNav(int nav)900   explicit FrameNavExpectationsBrowserTestSingleNav(int nav) : parent(nav) {}
901 
GetMainURL()902   std::string GetMainURL() override { return kFrameNavOrigin0; }
903 
GetContentForURL(const std::string & url)904   std::string GetContentForURL(const std::string& url) override {
905     return "<html><body>Nav</body></html>";
906   }
907 
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading)908   bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
909                             bool isLoading) override {
910     V_DECLARE();
911     V_EXPECT_TRUE(VerifySingleBrowserFrames(
912         browser, nullptr, isLoading ? std::string() : kFrameNavOrigin0));
913     V_EXPECT_TRUE(parent::OnLoadingStateChange(browser, isLoading));
914     V_RETURN();
915   }
916 
OnLoadStart(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)917   bool OnLoadStart(CefRefPtr<CefBrowser> browser,
918                    CefRefPtr<CefFrame> frame) override {
919     V_DECLARE();
920     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, kFrameNavOrigin0));
921     V_EXPECT_TRUE(parent::OnLoadStart(browser, frame));
922     V_RETURN();
923   }
924 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)925   bool OnLoadEnd(CefRefPtr<CefBrowser> browser,
926                  CefRefPtr<CefFrame> frame) override {
927     V_DECLARE();
928     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, kFrameNavOrigin0));
929     V_EXPECT_TRUE(parent::OnLoadEnd(browser, frame));
930     V_RETURN();
931   }
932 
OnAfterCreated(CefRefPtr<CefBrowser> browser)933   bool OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
934     V_DECLARE();
935     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, nullptr, std::string()));
936     V_EXPECT_TRUE(parent::OnAfterCreated(browser));
937     V_RETURN();
938   }
939 
OnBeforeBrowse(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & url)940   bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
941                       CefRefPtr<CefFrame> frame,
942                       const std::string& url) override {
943     V_DECLARE();
944     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, std::string()));
945     V_EXPECT_TRUE(parent::OnBeforeBrowse(browser, frame, url));
946     V_RETURN();
947   }
948 
GetResourceHandler(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)949   bool GetResourceHandler(CefRefPtr<CefBrowser> browser,
950                           CefRefPtr<CefFrame> frame) override {
951     V_DECLARE();
952     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, std::string()));
953     V_EXPECT_TRUE(parent::GetResourceHandler(browser, frame));
954     V_RETURN();
955   }
956 
OnRendererComplete(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int renderer_nav,bool renderer_result)957   bool OnRendererComplete(CefRefPtr<CefBrowser> browser,
958                           CefRefPtr<CefFrame> frame,
959                           int renderer_nav,
960                           bool renderer_result) override {
961     return parent::OnRendererComplete(browser, frame, renderer_nav,
962                                       renderer_result);
963   }
964 
Finalize()965   bool Finalize() override { return parent::Finalize(); }
966 };
967 
968 class FrameNavExpectationsRendererTestSingleNav
969     : public FrameNavExpectationsRendererSingleNav {
970  public:
971   typedef FrameNavExpectationsRendererSingleNav parent;
972 
FrameNavExpectationsRendererTestSingleNav(int nav)973   explicit FrameNavExpectationsRendererTestSingleNav(int nav) : parent(nav) {}
974 
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading)975   bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
976                             bool isLoading) override {
977     V_DECLARE();
978     // A frame should always exist in the renderer process.
979     V_EXPECT_TRUE(
980         VerifySingleBrowserFrames(browser, nullptr, kFrameNavOrigin0));
981     V_EXPECT_TRUE(parent::OnLoadingStateChange(browser, isLoading));
982     V_RETURN();
983   }
984 
OnLoadStart(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)985   bool OnLoadStart(CefRefPtr<CefBrowser> browser,
986                    CefRefPtr<CefFrame> frame) override {
987     V_DECLARE();
988     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, kFrameNavOrigin0));
989     V_EXPECT_TRUE(parent::OnLoadStart(browser, frame));
990     V_RETURN();
991   }
992 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)993   bool OnLoadEnd(CefRefPtr<CefBrowser> browser,
994                  CefRefPtr<CefFrame> frame) override {
995     V_DECLARE();
996     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, kFrameNavOrigin0));
997     V_EXPECT_TRUE(parent::OnLoadEnd(browser, frame));
998     V_RETURN();
999   }
1000 
Finalize()1001   bool Finalize() override { return parent::Finalize(); }
1002 };
1003 
1004 class FrameNavExpectationsFactoryBrowserTestSingleNav
1005     : public FrameNavExpectationsFactoryBrowser {
1006  public:
FrameNavExpectationsFactoryBrowserTestSingleNav()1007   FrameNavExpectationsFactoryBrowserTestSingleNav() {}
1008 
GetID() const1009   FrameNavFactoryId GetID() const override { return FNF_ID_SINGLE_NAV; }
1010 
HasMoreNavigations() const1011   bool HasMoreNavigations() const override { return false; }
1012 
Finalize()1013   bool Finalize() override { return true; }
1014 
1015  protected:
Create(int nav)1016   std::unique_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
1017     return std::make_unique<FrameNavExpectationsBrowserTestSingleNav>(nav);
1018   }
1019 };
1020 
1021 class FrameNavExpectationsFactoryRendererTestSingleNav
1022     : public FrameNavExpectationsFactoryRenderer {
1023  public:
FrameNavExpectationsFactoryRendererTestSingleNav()1024   FrameNavExpectationsFactoryRendererTestSingleNav() {}
1025 
GetID() const1026   FrameNavFactoryId GetID() const override { return FNF_ID_SINGLE_NAV; }
1027 
1028  protected:
Create(int nav)1029   std::unique_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
1030     return std::make_unique<FrameNavExpectationsRendererTestSingleNav>(nav);
1031   }
1032 };
1033 
1034 }  // namespace
1035 
1036 // Test that single navigation works.
1037 FRAME_TEST(SingleNav, FNF_ID_SINGLE_NAV)
1038 
1039 namespace {
1040 
1041 // Browser process expectations for a multiple navigations.
1042 class FrameNavExpectationsBrowserMultiNav : public FrameNavExpectationsBrowser {
1043  public:
FrameNavExpectationsBrowserMultiNav(int nav)1044   explicit FrameNavExpectationsBrowserMultiNav(int nav)
1045       : FrameNavExpectationsBrowser(nav) {}
1046 
~FrameNavExpectationsBrowserMultiNav()1047   ~FrameNavExpectationsBrowserMultiNav() override {
1048     EXPECT_TRUE(got_finalize_);
1049   }
1050 
1051   // Returns true if all navigation is done.
1052   virtual bool IsNavigationDone() const = 0;
1053 
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading)1054   bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
1055                             bool isLoading) override {
1056     if (!isLoading)
1057       SignalCompleteIfDone(browser, browser->GetMainFrame());
1058     return true;
1059   }
1060 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)1061   bool OnLoadEnd(CefRefPtr<CefBrowser> browser,
1062                  CefRefPtr<CefFrame> frame) override {
1063     SignalCompleteIfDone(browser, frame);
1064     return true;
1065   }
1066 
OnRendererComplete(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int renderer_nav,bool renderer_result)1067   bool OnRendererComplete(CefRefPtr<CefBrowser> browser,
1068                           CefRefPtr<CefFrame> frame,
1069                           int renderer_nav,
1070                           bool renderer_result) override {
1071     EXPECT_TRUE(renderer_result);
1072     SignalCompleteIfDone(browser, frame);
1073     return true;
1074   }
1075 
Finalize()1076   bool Finalize() override {
1077     V_DECLARE();
1078     V_EXPECT_FALSE(got_finalize_);
1079 
1080     got_finalize_.yes();
1081 
1082     V_RETURN();
1083   }
1084 
1085  private:
SignalCompleteIfDone(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)1086   void SignalCompleteIfDone(CefRefPtr<CefBrowser> browser,
1087                             CefRefPtr<CefFrame> frame) {
1088     if (IsNavigationDone())
1089       SignalComplete(browser, frame);
1090   }
1091 
1092   TrackCallback got_finalize_;
1093 };
1094 
1095 // Renderer process expectations for a multiple navigations.
1096 class FrameNavExpectationsRendererMultiNav
1097     : public FrameNavExpectationsRenderer {
1098  public:
FrameNavExpectationsRendererMultiNav(int nav)1099   explicit FrameNavExpectationsRendererMultiNav(int nav)
1100       : FrameNavExpectationsRenderer(nav) {}
1101 
~FrameNavExpectationsRendererMultiNav()1102   ~FrameNavExpectationsRendererMultiNav() override {
1103     EXPECT_TRUE(got_finalize_);
1104   }
1105 
1106   // Returns true if all navigation is done.
1107   virtual bool IsNavigationDone() const = 0;
1108 
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading)1109   bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
1110                             bool isLoading) override {
1111     if (!isLoading)
1112       SignalCompleteIfDone(browser, browser->GetMainFrame());
1113     return true;
1114   }
1115 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)1116   bool OnLoadEnd(CefRefPtr<CefBrowser> browser,
1117                  CefRefPtr<CefFrame> frame) override {
1118     SignalCompleteIfDone(browser, frame);
1119     return true;
1120   }
1121 
Finalize()1122   bool Finalize() override {
1123     V_DECLARE();
1124     V_EXPECT_FALSE(got_finalize_);
1125 
1126     got_finalize_.yes();
1127 
1128     V_RETURN();
1129   }
1130 
1131  private:
SignalCompleteIfDone(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)1132   void SignalCompleteIfDone(CefRefPtr<CefBrowser> browser,
1133                             CefRefPtr<CefFrame> frame) {
1134     if (IsNavigationDone())
1135       SignalComplete(browser, frame);
1136   }
1137 
1138   TrackCallback got_finalize_;
1139 };
1140 
1141 // Create a URL containing the nav number.
GetMultiNavURL(const std::string & origin,int nav)1142 std::string GetMultiNavURL(const std::string& origin, int nav) {
1143   std::stringstream ss;
1144   ss << origin << "nav" << nav << ".html";
1145   return ss.str();
1146 }
1147 
1148 // Extract the nav number from the URL.
GetNavFromMultiNavURL(const std::string & url)1149 int GetNavFromMultiNavURL(const std::string& url) {
1150   const size_t start = url.find("/nav");
1151   const size_t end = url.find(".html", start);
1152   EXPECT_TRUE(start < end && start > 0U);
1153   const std::string& nav = url.substr(start + 4, end - start - 4);
1154   return atoi(nav.c_str());
1155 }
1156 
1157 // Extract the origin from the URL.
GetOriginFromMultiNavURL(const std::string & url)1158 std::string GetOriginFromMultiNavURL(const std::string& url) {
1159   const size_t pos = url.rfind("/");
1160   EXPECT_TRUE(pos > 0U);
1161   return url.substr(0, pos + 1);
1162 }
1163 
1164 // Test that the multi nav harness works.
1165 class FrameNavExpectationsBrowserTestMultiNavHarness
1166     : public FrameNavExpectationsBrowserMultiNav {
1167  public:
1168   typedef FrameNavExpectationsBrowserMultiNav parent;
1169 
FrameNavExpectationsBrowserTestMultiNavHarness(int nav)1170   explicit FrameNavExpectationsBrowserTestMultiNavHarness(int nav)
1171       : parent(nav), navigation_done_count_(0) {}
1172 
~FrameNavExpectationsBrowserTestMultiNavHarness()1173   ~FrameNavExpectationsBrowserTestMultiNavHarness() override {
1174     EXPECT_TRUE(got_finalize_);
1175   }
1176 
GetMainURL()1177   std::string GetMainURL() override {
1178     EXPECT_FALSE(got_get_main_url_);
1179     got_get_main_url_.yes();
1180     return GetMultiNavURL(kFrameNavOrigin0, nav());
1181   }
1182 
GetContentForURL(const std::string & url)1183   std::string GetContentForURL(const std::string& url) override {
1184     EXPECT_FALSE(got_get_content_for_url_);
1185     got_get_content_for_url_.yes();
1186     EXPECT_STREQ(GetMultiNavURL(kFrameNavOrigin0, nav()).c_str(), url.c_str());
1187     return "<html><body>Nav</body></html>";
1188   }
1189 
IsNavigationDone() const1190   bool IsNavigationDone() const override {
1191     navigation_done_count_++;
1192     return got_load_state_change_done_ && got_load_end_ &&
1193            got_renderer_complete_;
1194   }
1195 
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading)1196   bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
1197                             bool isLoading) override {
1198     if (!isLoading) {
1199       EXPECT_FALSE(got_load_state_change_done_);
1200       got_load_state_change_done_.yes();
1201     }
1202     return parent::OnLoadingStateChange(browser, isLoading);
1203   }
1204 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)1205   bool OnLoadEnd(CefRefPtr<CefBrowser> browser,
1206                  CefRefPtr<CefFrame> frame) override {
1207     EXPECT_FALSE(got_load_end_);
1208     got_load_end_.yes();
1209     return parent::OnLoadEnd(browser, frame);
1210   }
1211 
OnAfterCreated(CefRefPtr<CefBrowser> browser)1212   bool OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
1213     EXPECT_FALSE(got_on_after_created_);
1214     got_on_after_created_.yes();
1215     return parent::OnAfterCreated(browser);
1216   }
1217 
OnRendererComplete(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int renderer_nav,bool renderer_result)1218   bool OnRendererComplete(CefRefPtr<CefBrowser> browser,
1219                           CefRefPtr<CefFrame> frame,
1220                           int renderer_nav,
1221                           bool renderer_result) override {
1222     EXPECT_FALSE(got_renderer_complete_);
1223     got_renderer_complete_.yes();
1224     EXPECT_EQ(nav(), renderer_nav);
1225     return parent::OnRendererComplete(browser, frame, renderer_nav,
1226                                       renderer_result);
1227   }
1228 
Finalize()1229   bool Finalize() override {
1230     EXPECT_FALSE(got_finalize_);
1231     got_finalize_.yes();
1232 
1233     V_DECLARE();
1234     V_EXPECT_TRUE(got_get_main_url_);
1235     V_EXPECT_TRUE(got_get_content_for_url_);
1236     V_EXPECT_TRUE(got_load_state_change_done_);
1237     V_EXPECT_TRUE(got_load_end_);
1238     if (nav() == 0) {
1239       V_EXPECT_TRUE(got_on_after_created_);
1240     } else {
1241       V_EXPECT_FALSE(got_on_after_created_);
1242     }
1243     V_EXPECT_TRUE(got_renderer_complete_);
1244     V_EXPECT_TRUE(navigation_done_count_ == 3);
1245     V_EXPECT_TRUE(parent::Finalize());
1246     V_RETURN();
1247   }
1248 
1249  private:
1250   TrackCallback got_get_main_url_;
1251   TrackCallback got_get_content_for_url_;
1252   TrackCallback got_load_state_change_done_;
1253   TrackCallback got_load_end_;
1254   TrackCallback got_on_after_created_;
1255   TrackCallback got_renderer_complete_;
1256   mutable int navigation_done_count_;
1257   TrackCallback got_finalize_;
1258 };
1259 
1260 class FrameNavExpectationsRendererTestMultiNavHarness
1261     : public FrameNavExpectationsRendererMultiNav {
1262  public:
1263   typedef FrameNavExpectationsRendererMultiNav parent;
1264 
FrameNavExpectationsRendererTestMultiNavHarness(int nav)1265   explicit FrameNavExpectationsRendererTestMultiNavHarness(int nav)
1266       : parent(nav), navigation_done_count_(0) {}
1267 
~FrameNavExpectationsRendererTestMultiNavHarness()1268   ~FrameNavExpectationsRendererTestMultiNavHarness() override {
1269     EXPECT_TRUE(got_finalize_);
1270   }
1271 
IsNavigationDone() const1272   bool IsNavigationDone() const override {
1273     navigation_done_count_++;
1274     return got_load_state_change_done_ && got_load_end_;
1275   }
1276 
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading)1277   bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
1278                             bool isLoading) override {
1279     if (!isLoading) {
1280       EXPECT_FALSE(got_load_state_change_done_);
1281       got_load_state_change_done_.yes();
1282     }
1283     return parent::OnLoadingStateChange(browser, isLoading);
1284   }
1285 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)1286   bool OnLoadEnd(CefRefPtr<CefBrowser> browser,
1287                  CefRefPtr<CefFrame> frame) override {
1288     EXPECT_FALSE(got_load_end_);
1289     got_load_end_.yes();
1290     return parent::OnLoadEnd(browser, frame);
1291   }
1292 
Finalize()1293   bool Finalize() override {
1294     EXPECT_FALSE(got_finalize_);
1295     got_finalize_.yes();
1296 
1297     V_DECLARE();
1298     V_EXPECT_TRUE(got_load_state_change_done_);
1299     V_EXPECT_TRUE(got_load_end_);
1300     V_EXPECT_TRUE(navigation_done_count_ == 2);
1301     V_EXPECT_TRUE(parent::Finalize());
1302     V_RETURN();
1303   }
1304 
1305  private:
1306   TrackCallback got_load_state_change_done_;
1307   TrackCallback got_load_end_;
1308   mutable int navigation_done_count_;
1309   TrackCallback got_finalize_;
1310 };
1311 
1312 class FrameNavExpectationsFactoryBrowserTestMultiNavHarness
1313     : public FrameNavExpectationsFactoryBrowser {
1314  public:
FrameNavExpectationsFactoryBrowserTestMultiNavHarness()1315   FrameNavExpectationsFactoryBrowserTestMultiNavHarness()
1316       : get_browser_navigation_count_(0), create_count_(0) {}
1317 
~FrameNavExpectationsFactoryBrowserTestMultiNavHarness()1318   ~FrameNavExpectationsFactoryBrowserTestMultiNavHarness() override {
1319     EXPECT_TRUE(got_finalize_);
1320   }
1321 
GetID() const1322   FrameNavFactoryId GetID() const override { return FNF_ID_MULTI_NAV_HARNESS; }
1323 
HasMoreNavigations() const1324   bool HasMoreNavigations() const override {
1325     get_browser_navigation_count_++;
1326     return (get_browser_navigation_count_ < kMaxMultiNavNavigations);
1327   }
1328 
Finalize()1329   bool Finalize() override {
1330     EXPECT_FALSE(got_finalize_);
1331     got_finalize_.yes();
1332 
1333     V_DECLARE();
1334     V_EXPECT_TRUE(get_browser_navigation_count_ == kMaxMultiNavNavigations);
1335     V_EXPECT_TRUE(create_count_ == kMaxMultiNavNavigations);
1336     V_RETURN();
1337   }
1338 
1339  protected:
Create(int nav)1340   std::unique_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
1341     create_count_++;
1342     return std::make_unique<FrameNavExpectationsBrowserTestMultiNavHarness>(
1343         nav);
1344   }
1345 
1346  private:
1347   mutable int get_browser_navigation_count_;
1348   int create_count_;
1349   TrackCallback got_finalize_;
1350 };
1351 
1352 class FrameNavExpectationsFactoryRendererTestMultiNavHarness
1353     : public FrameNavExpectationsFactoryRenderer {
1354  public:
FrameNavExpectationsFactoryRendererTestMultiNavHarness()1355   FrameNavExpectationsFactoryRendererTestMultiNavHarness() {}
1356 
GetID() const1357   FrameNavFactoryId GetID() const override { return FNF_ID_MULTI_NAV_HARNESS; }
1358 
1359  protected:
Create(int nav)1360   std::unique_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
1361     return std::make_unique<FrameNavExpectationsRendererTestMultiNavHarness>(
1362         nav);
1363   }
1364 };
1365 
1366 }  // namespace
1367 
1368 // Test that the multiple nav harness works.
1369 FRAME_TEST(MultiNavHarness, FNF_ID_MULTI_NAV_HARNESS)
1370 
1371 namespace {
1372 
1373 // Test that multiple navigation works.
1374 class FrameNavExpectationsBrowserTestMultiNav
1375     : public FrameNavExpectationsBrowserMultiNav {
1376  public:
1377   typedef FrameNavExpectationsBrowserMultiNav parent;
1378 
FrameNavExpectationsBrowserTestMultiNav(int nav)1379   explicit FrameNavExpectationsBrowserTestMultiNav(int nav) : parent(nav) {}
1380 
GetMainURL()1381   std::string GetMainURL() override {
1382     return GetMultiNavURL(kFrameNavOrigin0, nav());
1383   }
1384 
GetContentForURL(const std::string & url)1385   std::string GetContentForURL(const std::string& url) override {
1386     return "<html><body>Nav</body></html>";
1387   }
1388 
IsNavigationDone() const1389   bool IsNavigationDone() const override {
1390     return got_load_state_change_done_ && got_load_end_ &&
1391            got_renderer_complete_;
1392   }
1393 
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading)1394   bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
1395                             bool isLoading) override {
1396     if (!isLoading)
1397       got_load_state_change_done_.yes();
1398     V_DECLARE();
1399     if (isLoading && nav() == 0) {
1400       V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, nullptr, std::string()));
1401     } else if (isLoading) {
1402       // Expect the URL from the previous load.
1403       V_EXPECT_TRUE(
1404           VerifySingleBrowserFrames(browser, nullptr, GetPreviousMainURL()));
1405     } else {
1406       V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, nullptr, GetMainURL()));
1407     }
1408     V_EXPECT_TRUE(parent::OnLoadingStateChange(browser, isLoading));
1409     V_RETURN();
1410   }
1411 
OnLoadStart(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)1412   bool OnLoadStart(CefRefPtr<CefBrowser> browser,
1413                    CefRefPtr<CefFrame> frame) override {
1414     V_DECLARE();
1415     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, GetMainURL()));
1416     V_EXPECT_TRUE(parent::OnLoadStart(browser, frame));
1417     V_RETURN();
1418   }
1419 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)1420   bool OnLoadEnd(CefRefPtr<CefBrowser> browser,
1421                  CefRefPtr<CefFrame> frame) override {
1422     got_load_end_.yes();
1423     V_DECLARE();
1424     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, GetMainURL()));
1425     V_EXPECT_TRUE(parent::OnLoadEnd(browser, frame));
1426     V_RETURN();
1427   }
1428 
OnAfterCreated(CefRefPtr<CefBrowser> browser)1429   bool OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
1430     V_DECLARE();
1431     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, nullptr, std::string()));
1432     V_EXPECT_TRUE(parent::OnAfterCreated(browser));
1433     V_RETURN();
1434   }
1435 
OnBeforeBrowse(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & url)1436   bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
1437                       CefRefPtr<CefFrame> frame,
1438                       const std::string& url) override {
1439     V_DECLARE();
1440     std::string expected_url;
1441     if (nav() > 0)
1442       expected_url = GetPreviousMainURL();
1443     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, expected_url));
1444     V_EXPECT_TRUE(parent::OnBeforeBrowse(browser, frame, url));
1445     V_RETURN();
1446   }
1447 
GetResourceHandler(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)1448   bool GetResourceHandler(CefRefPtr<CefBrowser> browser,
1449                           CefRefPtr<CefFrame> frame) override {
1450     V_DECLARE();
1451     std::string expected_url;
1452     if (nav() > 0)
1453       expected_url = GetPreviousMainURL();
1454     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, expected_url));
1455     V_EXPECT_TRUE(parent::GetResourceHandler(browser, frame));
1456     V_RETURN();
1457   }
1458 
OnRendererComplete(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int renderer_nav,bool renderer_result)1459   bool OnRendererComplete(CefRefPtr<CefBrowser> browser,
1460                           CefRefPtr<CefFrame> frame,
1461                           int renderer_nav,
1462                           bool renderer_result) override {
1463     got_renderer_complete_.yes();
1464     V_DECLARE();
1465     V_EXPECT_TRUE(nav() == renderer_nav);
1466     V_EXPECT_TRUE(parent::OnRendererComplete(browser, frame, renderer_nav,
1467                                              renderer_result));
1468     V_RETURN();
1469   }
1470 
Finalize()1471   bool Finalize() override {
1472     V_DECLARE();
1473     V_EXPECT_TRUE(got_load_state_change_done_);
1474     V_EXPECT_TRUE(got_load_end_);
1475     V_EXPECT_TRUE(got_renderer_complete_);
1476     V_EXPECT_TRUE(parent::Finalize());
1477     V_RETURN();
1478   }
1479 
1480  private:
1481   // Helper for VerifySingleBrowserFrames.
GetPreviousMainURL()1482   std::string GetPreviousMainURL() {
1483     EXPECT_GT(nav(), 0);
1484     return GetMultiNavURL(kFrameNavOrigin0, nav() - 1);
1485   }
1486 
1487   TrackCallback got_load_state_change_done_;
1488   TrackCallback got_load_end_;
1489   TrackCallback got_renderer_complete_;
1490 };
1491 
1492 class FrameNavExpectationsRendererTestMultiNav
1493     : public FrameNavExpectationsRendererMultiNav {
1494  public:
1495   typedef FrameNavExpectationsRendererMultiNav parent;
1496 
FrameNavExpectationsRendererTestMultiNav(int nav)1497   explicit FrameNavExpectationsRendererTestMultiNav(int nav) : parent(nav) {}
1498 
IsNavigationDone() const1499   bool IsNavigationDone() const override {
1500     return got_load_state_change_done_ && got_load_end_;
1501   }
1502 
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading)1503   bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
1504                             bool isLoading) override {
1505     if (!isLoading)
1506       got_load_state_change_done_.yes();
1507     V_DECLARE();
1508     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, nullptr, GetMainURL()));
1509     V_EXPECT_TRUE(parent::OnLoadingStateChange(browser, isLoading));
1510     V_RETURN();
1511   }
1512 
OnLoadStart(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)1513   bool OnLoadStart(CefRefPtr<CefBrowser> browser,
1514                    CefRefPtr<CefFrame> frame) override {
1515     V_DECLARE();
1516     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, GetMainURL()));
1517     V_EXPECT_TRUE(parent::OnLoadStart(browser, frame));
1518     V_RETURN();
1519   }
1520 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)1521   bool OnLoadEnd(CefRefPtr<CefBrowser> browser,
1522                  CefRefPtr<CefFrame> frame) override {
1523     got_load_end_.yes();
1524     V_DECLARE();
1525     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, GetMainURL()));
1526     V_EXPECT_TRUE(parent::OnLoadEnd(browser, frame));
1527     V_RETURN();
1528   }
1529 
Finalize()1530   bool Finalize() override {
1531     V_DECLARE();
1532     V_EXPECT_TRUE(got_load_state_change_done_);
1533     V_EXPECT_TRUE(got_load_end_);
1534     V_EXPECT_TRUE(parent::Finalize());
1535     V_RETURN();
1536   }
1537 
1538  private:
1539   // Helpers for calling VerifySingleBrowserFrames.
GetMainURL() const1540   std::string GetMainURL() const {
1541     return GetMultiNavURL(kFrameNavOrigin0, nav());
1542   }
GetPreviousMainURL()1543   std::string GetPreviousMainURL() {
1544     EXPECT_GT(nav(), 0);
1545     return GetMultiNavURL(kFrameNavOrigin0, nav() - 1);
1546   }
1547 
1548   TrackCallback got_load_state_change_done_;
1549   TrackCallback got_load_end_;
1550 };
1551 
1552 class FrameNavExpectationsFactoryBrowserTestMultiNav
1553     : public FrameNavExpectationsFactoryBrowser {
1554  public:
FrameNavExpectationsFactoryBrowserTestMultiNav()1555   FrameNavExpectationsFactoryBrowserTestMultiNav() : nav_count_(0) {}
1556 
GetID() const1557   FrameNavFactoryId GetID() const override { return FNF_ID_MULTI_NAV; }
1558 
HasMoreNavigations() const1559   bool HasMoreNavigations() const override {
1560     return (nav_count_ < kMaxMultiNavNavigations);
1561   }
1562 
Finalize()1563   bool Finalize() override {
1564     V_DECLARE();
1565     V_EXPECT_TRUE(nav_count_ == kMaxMultiNavNavigations);
1566     V_RETURN();
1567   }
1568 
1569  protected:
Create(int nav)1570   std::unique_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
1571     nav_count_++;
1572     return std::make_unique<FrameNavExpectationsBrowserTestMultiNav>(nav);
1573   }
1574 
1575  private:
1576   int nav_count_;
1577 };
1578 
1579 class FrameNavExpectationsFactoryRendererTestMultiNav
1580     : public FrameNavExpectationsFactoryRenderer {
1581  public:
FrameNavExpectationsFactoryRendererTestMultiNav()1582   FrameNavExpectationsFactoryRendererTestMultiNav() {}
1583 
GetID() const1584   FrameNavFactoryId GetID() const override { return FNF_ID_MULTI_NAV; }
1585 
1586  protected:
Create(int nav)1587   std::unique_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
1588     return std::make_unique<FrameNavExpectationsRendererTestMultiNav>(nav);
1589   }
1590 };
1591 
1592 }  // namespace
1593 
1594 // Test that multiple navigation works.
1595 FRAME_TEST(MultiNav, FNF_ID_MULTI_NAV)
1596 
1597 namespace {
1598 
1599 const char kFrame0Name[] = "";
1600 const char kFrame1Name[] = "nav2";
1601 const char kFrame2Name[] = "<!--framePath //nav2/<!--frame0-->-->";
1602 const char kFrame3Name[] = "nav3";
1603 
VerifyBrowserIframe(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & origin,int frame_number)1604 bool VerifyBrowserIframe(CefRefPtr<CefBrowser> browser,
1605                          CefRefPtr<CefFrame> frame,
1606                          const std::string& origin,
1607                          int frame_number) {
1608   V_DECLARE();
1609 
1610   // frame0 contains frame1 contains frame2, contains frame3.
1611   CefRefPtr<CefFrame> frame0, frame1, frame2, frame3;
1612   CefRefPtr<CefFrame> frame0b, frame1b, frame2b, frame3b;
1613   int64 frame0id, frame1id, frame2id, frame3id;
1614   std::string frame0url, frame1url, frame2url, frame3url;
1615 
1616   // Verify the GetFrameNames result.
1617   std::set<std::string> expected_names = {kFrame0Name, kFrame1Name, kFrame2Name,
1618                                           kFrame3Name};
1619 
1620   std::vector<CefString> names;
1621   browser->GetFrameNames(names);
1622   V_EXPECT_TRUE(names.size() == expected_names.size())
1623       << "expected: " << expected_names.size() << " actual: " << names.size();
1624 
1625   for (const auto& name : names) {
1626     const std::string& nameStr = name;
1627     auto it = expected_names.find(nameStr);
1628     V_EXPECT_FALSE(it == expected_names.end())
1629         << "Unexpected name: \"" << nameStr << "\"";
1630     if (it != expected_names.end())
1631       expected_names.erase(it);
1632   }
1633 
1634   for (const auto& name : expected_names) {
1635     V_EXPECT_FALSE(true) << "Missing name: \"" << name << "\"";
1636   }
1637 
1638   // Find frames by name.
1639   frame0 = browser->GetFrame(kFrame0Name);
1640   V_EXPECT_TRUE(frame0.get());
1641   frame1 = browser->GetFrame(kFrame1Name);
1642   V_EXPECT_TRUE(frame1.get());
1643   frame2 = browser->GetFrame(kFrame2Name);
1644   V_EXPECT_TRUE(frame2.get());
1645   frame3 = browser->GetFrame(kFrame3Name);
1646   V_EXPECT_TRUE(frame3.get());
1647 
1648   if (!frame0 || !frame1 || !frame2 || !frame3) {
1649     V_RETURN();
1650   }
1651 
1652   // Verify that the name matches.
1653   V_EXPECT_TRUE(frame0->GetName().ToString() == kFrame0Name)
1654       << "expected: " << kFrame0Name
1655       << " actual: " << frame0->GetName().ToString();
1656   V_EXPECT_TRUE(frame1->GetName().ToString() == kFrame1Name)
1657       << "expected: " << kFrame1Name
1658       << " actual: " << frame1->GetName().ToString();
1659   V_EXPECT_TRUE(frame2->GetName().ToString() == kFrame2Name)
1660       << "expected: " << kFrame2Name
1661       << " actual: " << frame2->GetName().ToString();
1662   V_EXPECT_TRUE(frame3->GetName().ToString() == kFrame3Name)
1663       << "expected: " << kFrame3Name
1664       << " actual: " << frame3->GetName().ToString();
1665 
1666   // Verify that the URL matches.
1667   frame0url = GetMultiNavURL(origin, 0);
1668   V_EXPECT_TRUE(frame0->GetURL() == frame0url)
1669       << "expected: " << frame0url
1670       << " actual: " << frame0->GetURL().ToString();
1671   frame1url = GetMultiNavURL(origin, 1);
1672   V_EXPECT_TRUE(frame1->GetURL() == frame1url)
1673       << "expected: " << frame1url
1674       << " actual: " << frame1->GetURL().ToString();
1675   frame2url = GetMultiNavURL(origin, 2);
1676   V_EXPECT_TRUE(frame2->GetURL() == frame2url)
1677       << "expected: " << frame2url
1678       << " actual: " << frame2->GetURL().ToString();
1679   frame3url = GetMultiNavURL(origin, 3);
1680   V_EXPECT_TRUE(frame3->GetURL() == frame3url)
1681       << "expected: " << frame3url
1682       << " actual: " << frame3->GetURL().ToString();
1683 
1684   // Verify that the frame id is valid.
1685   frame0id = frame0->GetIdentifier();
1686   V_EXPECT_TRUE(frame0id > 0) << "actual: " << frame0id;
1687   frame1id = frame1->GetIdentifier();
1688   V_EXPECT_TRUE(frame1id > 0) << "actual: " << frame1id;
1689   frame2id = frame2->GetIdentifier();
1690   V_EXPECT_TRUE(frame2id > 0) << "actual: " << frame2id;
1691   frame3id = frame3->GetIdentifier();
1692   V_EXPECT_TRUE(frame3id > 0) << "actual: " << frame3id;
1693 
1694   // Verify that the current frame has the correct id.
1695   if (frame_number == 0) {
1696     V_EXPECT_TRUE(frame->GetIdentifier() == frame0id)
1697         << "expected: " << frame0id << " actual: " << frame->GetIdentifier();
1698   } else if (frame_number == 1) {
1699     V_EXPECT_TRUE(frame->GetIdentifier() == frame1id)
1700         << "expected: " << frame1id << " actual: " << frame->GetIdentifier();
1701   } else if (frame_number == 2) {
1702     V_EXPECT_TRUE(frame->GetIdentifier() == frame2id)
1703         << "expected: " << frame2id << " actual: " << frame->GetIdentifier();
1704   } else if (frame_number == 3) {
1705     V_EXPECT_TRUE(frame->GetIdentifier() == frame3id)
1706         << "expected: " << frame3id << " actual: " << frame->GetIdentifier();
1707   }
1708 
1709   // Find frames by id.
1710   frame0b = browser->GetFrame(frame0->GetIdentifier());
1711   V_EXPECT_TRUE(frame0b.get());
1712   frame1b = browser->GetFrame(frame1->GetIdentifier());
1713   V_EXPECT_TRUE(frame1b.get());
1714   frame2b = browser->GetFrame(frame2->GetIdentifier());
1715   V_EXPECT_TRUE(frame2b.get());
1716   frame3b = browser->GetFrame(frame3->GetIdentifier());
1717   V_EXPECT_TRUE(frame3b.get());
1718 
1719   if (!frame0b || !frame1b || !frame2b || !frame3b) {
1720     V_RETURN();
1721   }
1722 
1723   // Verify that the id matches.
1724   V_EXPECT_TRUE(frame0b->GetIdentifier() == frame0id)
1725       << "expected: " << frame0id << " actual: " << frame0b->GetIdentifier();
1726   V_EXPECT_TRUE(frame1b->GetIdentifier() == frame1id)
1727       << "expected: " << frame1id << " actual: " << frame1b->GetIdentifier();
1728   V_EXPECT_TRUE(frame2b->GetIdentifier() == frame2id)
1729       << "expected: " << frame2id << " actual: " << frame2b->GetIdentifier();
1730   V_EXPECT_TRUE(frame3b->GetIdentifier() == frame3id)
1731       << "expected: " << frame3id << " actual: " << frame3b->GetIdentifier();
1732 
1733   size_t frame_count = browser->GetFrameCount();
1734   V_EXPECT_TRUE(frame_count == 4U) << " actual: " << frame_count;
1735 
1736   // Verify the GetFrameIdentifiers result.
1737   std::set<int64> expected_idents = {frame0id, frame1id, frame2id, frame3id};
1738 
1739   std::vector<int64> idents;
1740   browser->GetFrameIdentifiers(idents);
1741   V_EXPECT_TRUE(idents.size() == expected_idents.size())
1742       << "expected: " << expected_idents.size() << " actual: " << idents.size();
1743 
1744   for (const auto& ident : idents) {
1745     auto it = expected_idents.find(ident);
1746     V_EXPECT_FALSE(it == expected_idents.end()) << "Unexpected id: " << ident;
1747     if (it != expected_idents.end())
1748       expected_idents.erase(it);
1749   }
1750 
1751   for (const auto& ident : expected_idents) {
1752     V_EXPECT_FALSE(true) << "Missing id: " << ident;
1753   }
1754 
1755   // Verify parent hierarchy.
1756   V_EXPECT_FALSE(frame0->GetParent().get());
1757   V_EXPECT_TRUE(frame1->GetParent()->GetIdentifier() == frame0id)
1758       << "expected: " << frame0id
1759       << " actual: " << frame1->GetParent()->GetIdentifier();
1760   V_EXPECT_TRUE(frame2->GetParent()->GetIdentifier() == frame1id)
1761       << "expected: " << frame1id
1762       << " actual: " << frame2->GetParent()->GetIdentifier();
1763   V_EXPECT_TRUE(frame3->GetParent()->GetIdentifier() == frame2id)
1764       << "expected: " << frame2id
1765       << " actual: " << frame3->GetParent()->GetIdentifier();
1766 
1767   V_RETURN();
1768 }
1769 
1770 // Test that nested iframes work.
1771 class FrameNavExpectationsBrowserTestNestedIframes
1772     : public FrameNavExpectationsBrowserMultiNav {
1773  public:
1774   typedef FrameNavExpectationsBrowserMultiNav parent;
1775 
FrameNavExpectationsBrowserTestNestedIframes(int nav,bool same_origin)1776   FrameNavExpectationsBrowserTestNestedIframes(int nav, bool same_origin)
1777       : parent(nav), same_origin_(same_origin) {
1778     // In the browser process we can rely on the |nav| value to determine the
1779     // origin.
1780     if (same_origin) {
1781       origin_ = kFrameNavOrigin0;
1782     } else {
1783       switch (nav) {
1784         case 0:
1785           origin_ = kFrameNavOrigin0;
1786           break;
1787         case 1:
1788           origin_ = kFrameNavOrigin1;
1789           break;
1790         case 2:
1791           origin_ = kFrameNavOrigin2;
1792           break;
1793         case 3:
1794           origin_ = kFrameNavOrigin3;
1795           break;
1796         default:
1797           EXPECT_TRUE(false);  // Not reached.
1798           break;
1799       }
1800     }
1801   }
1802 
GetMainURL()1803   std::string GetMainURL() override {
1804     // Load the first (main) frame.
1805     return GetMultiNavURL(origin_, 0);
1806   }
1807 
GetContentForURL(const std::string & url)1808   std::string GetContentForURL(const std::string& url) override {
1809     const int frame_number = GetNavFromMultiNavURL(url);
1810     switch (frame_number) {
1811       case 0:
1812         // Frame 0. Contains a named iframe.
1813         return "<html><body>Nav1<iframe src=\"" + GetMultiNavURL(origin_, 1) +
1814                "\" name=\"nav2\"></body></html>";
1815       case 1:
1816         // Frame 1. Contains an unnamed iframe.
1817         return "<html><body>Nav2<iframe src=\"" + GetMultiNavURL(origin_, 2) +
1818                "\"></body></html>";
1819       case 2: {
1820         // Frame 2. Contains an named iframe created via javascript.
1821         std::stringstream ss;
1822         ss << "<html><script>"
1823            << "  function createFrame() {"
1824            << "    var f = document.createElement('iframe');"
1825            << "    f.name = 'nav3';"
1826            << "    f.src = '" << GetMultiNavURL(origin_, 3) << "';"
1827            << "    document.body.appendChild(f);"
1828            << "  }</script><body onload=\"createFrame()\">Nav3</body></html>";
1829         return ss.str();
1830       }
1831       case 3:
1832         // Frame 3.
1833         return "<html><body>Nav4</body></html>";
1834       default:
1835         EXPECT_TRUE(false);  // Not reached.
1836         return "";
1837     }
1838   }
1839 
IsNavigationDone() const1840   bool IsNavigationDone() const override {
1841     return got_load_state_change_done_ && got_renderer_complete_ &&
1842            got_load_end_[0] && got_load_end_[1] && got_load_end_[2] &&
1843            got_load_end_[3];
1844   }
1845 
OnBeforeBrowse(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & url)1846   bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
1847                       CefRefPtr<CefFrame> frame,
1848                       const std::string& url) override {
1849     V_DECLARE();
1850     V_EXPECT_TRUE(frame.get());
1851     const int frame_number = GetNavFromMultiNavURL(url);
1852     if (frame_number == 0) {
1853       // Main frame.
1854       V_EXPECT_TRUE(frame->IsMain());
1855     } else {
1856       // Sub frame.
1857       V_EXPECT_FALSE(frame->IsMain());
1858     }
1859     V_EXPECT_TRUE(parent::OnBeforeBrowse(browser, frame, url));
1860     V_RETURN();
1861   }
1862 
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading)1863   bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
1864                             bool isLoading) override {
1865     V_DECLARE();
1866     V_EXPECT_FALSE(got_load_state_change_done_);
1867 
1868     if (!isLoading) {
1869       got_load_state_change_done_.yes();
1870     }
1871 
1872     V_EXPECT_TRUE(parent::OnLoadingStateChange(browser, isLoading));
1873     V_RETURN();
1874   }
1875 
OnLoadStart(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)1876   bool OnLoadStart(CefRefPtr<CefBrowser> browser,
1877                    CefRefPtr<CefFrame> frame) override {
1878     const int frame_number = GetNavFromMultiNavURL(frame->GetURL());
1879 
1880     V_DECLARE();
1881     V_EXPECT_FALSE(got_load_start_[frame_number]);
1882     V_EXPECT_FALSE(got_load_end_[frame_number]);
1883 
1884     // Notification should be received for parent frame before child frame.
1885     if (frame_number == 0) {
1886       V_EXPECT_FALSE(got_load_start_[1]);
1887       V_EXPECT_FALSE(got_load_start_[2]);
1888       V_EXPECT_FALSE(got_load_start_[3]);
1889     } else if (frame_number == 1) {
1890       V_EXPECT_TRUE(got_load_start_[0]);
1891       V_EXPECT_FALSE(got_load_start_[2]);
1892       V_EXPECT_FALSE(got_load_start_[3]);
1893     } else if (frame_number == 2) {
1894       V_EXPECT_TRUE(got_load_start_[0]);
1895       V_EXPECT_TRUE(got_load_start_[1]);
1896       V_EXPECT_FALSE(got_load_start_[3]);
1897     } else if (frame_number == 3) {
1898       V_EXPECT_TRUE(got_load_start_[0]);
1899       V_EXPECT_TRUE(got_load_start_[1]);
1900       V_EXPECT_TRUE(got_load_start_[2]);
1901     } else {
1902       V_EXPECT_TRUE(false);  // Not reached.
1903     }
1904 
1905     got_load_start_[frame_number].yes();
1906 
1907     V_EXPECT_TRUE(parent::OnLoadStart(browser, frame));
1908     V_RETURN();
1909   }
1910 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)1911   bool OnLoadEnd(CefRefPtr<CefBrowser> browser,
1912                  CefRefPtr<CefFrame> frame) override {
1913     const int frame_number = GetNavFromMultiNavURL(frame->GetURL());
1914 
1915     V_DECLARE();
1916     V_EXPECT_TRUE(got_load_start_[frame_number]);
1917     V_EXPECT_FALSE(got_load_end_[frame_number]);
1918 
1919     // Notification should be received for child frame before parent frame.
1920     if (frame_number == 0) {
1921       V_EXPECT_TRUE(got_load_end_[1]);
1922       V_EXPECT_TRUE(got_load_end_[2]);
1923       V_EXPECT_TRUE(got_load_end_[3]);
1924     } else if (frame_number == 1) {
1925       V_EXPECT_FALSE(got_load_end_[0]);
1926       V_EXPECT_TRUE(got_load_end_[2]);
1927       V_EXPECT_TRUE(got_load_end_[3]);
1928     } else if (frame_number == 2) {
1929       V_EXPECT_FALSE(got_load_end_[0]);
1930       V_EXPECT_FALSE(got_load_end_[1]);
1931       V_EXPECT_TRUE(got_load_end_[3]);
1932     } else if (frame_number == 3) {
1933       V_EXPECT_FALSE(got_load_end_[0]);
1934       V_EXPECT_FALSE(got_load_end_[1]);
1935       V_EXPECT_FALSE(got_load_end_[2]);
1936     } else {
1937       V_EXPECT_TRUE(false);  // Not reached.
1938     }
1939 
1940     V_EXPECT_TRUE(VerifyBrowserIframe(browser, frame, origin_, frame_number))
1941         << "frame_number = " << frame_number;
1942 
1943     got_load_end_[frame_number].yes();
1944 
1945     V_EXPECT_TRUE(parent::OnLoadEnd(browser, frame));
1946     V_RETURN();
1947   }
1948 
OnRendererComplete(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int renderer_nav,bool renderer_result)1949   bool OnRendererComplete(CefRefPtr<CefBrowser> browser,
1950                           CefRefPtr<CefFrame> frame,
1951                           int renderer_nav,
1952                           bool renderer_result) override {
1953     V_DECLARE();
1954     V_EXPECT_FALSE(got_renderer_complete_);
1955     if (same_origin_) {
1956       V_EXPECT_TRUE(renderer_nav == nav());
1957     } else {
1958       // Because each navigation is in a new renderer process.
1959       V_EXPECT_TRUE(renderer_nav == 0);
1960     }
1961 
1962     got_renderer_complete_.yes();
1963 
1964     V_EXPECT_TRUE(parent::OnRendererComplete(browser, frame, renderer_nav,
1965                                              renderer_result));
1966     V_RETURN();
1967   }
1968 
Finalize()1969   bool Finalize() override {
1970     V_DECLARE();
1971     V_EXPECT_TRUE(got_load_state_change_done_);
1972     V_EXPECT_TRUE(got_load_start_[0]);
1973     V_EXPECT_TRUE(got_load_start_[1]);
1974     V_EXPECT_TRUE(got_load_start_[2]);
1975     V_EXPECT_TRUE(got_load_start_[3]);
1976     V_EXPECT_TRUE(got_load_end_[0]);
1977     V_EXPECT_TRUE(got_load_end_[1]);
1978     V_EXPECT_TRUE(got_load_end_[2]);
1979     V_EXPECT_TRUE(got_load_end_[3]);
1980     V_EXPECT_TRUE(got_renderer_complete_);
1981     V_EXPECT_TRUE(parent::Finalize());
1982     V_RETURN();
1983   }
1984 
1985  private:
1986   bool same_origin_;
1987   std::string origin_;
1988 
1989   TrackCallback got_load_state_change_done_;
1990   TrackCallback got_load_start_[4];
1991   TrackCallback got_load_end_[4];
1992   TrackCallback got_renderer_complete_;
1993 };
1994 
1995 class FrameNavExpectationsRendererTestNestedIframes
1996     : public FrameNavExpectationsRendererMultiNav {
1997  public:
1998   typedef FrameNavExpectationsRendererMultiNav parent;
1999 
FrameNavExpectationsRendererTestNestedIframes(int nav,bool same_origin)2000   FrameNavExpectationsRendererTestNestedIframes(int nav, bool same_origin)
2001       : parent(nav) {
2002     if (same_origin)
2003       origin_ = kFrameNavOrigin0;
2004   }
2005 
IsNavigationDone() const2006   bool IsNavigationDone() const override {
2007     return got_load_state_change_done_ && got_load_end_[0] &&
2008            got_load_end_[1] && got_load_end_[2] && got_load_end_[3];
2009   }
2010 
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading)2011   bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
2012                             bool isLoading) override {
2013     V_DECLARE();
2014     V_EXPECT_FALSE(got_load_state_change_done_);
2015 
2016     if (!isLoading) {
2017       got_load_state_change_done_.yes();
2018     }
2019 
2020     V_EXPECT_TRUE(parent::OnLoadingStateChange(browser, isLoading));
2021     V_RETURN();
2022   }
2023 
OnLoadStart(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)2024   bool OnLoadStart(CefRefPtr<CefBrowser> browser,
2025                    CefRefPtr<CefFrame> frame) override {
2026     if (origin_.empty()) {
2027       // When navigating different origins we can't rely on the nav() value
2028       // because each navigation creates a new renderer process. Get the origin
2029       // by parsing the URL instead.
2030       origin_ = GetOriginFromMultiNavURL(browser->GetMainFrame()->GetURL());
2031     }
2032 
2033     const int frame_number = GetNavFromMultiNavURL(frame->GetURL());
2034 
2035     V_DECLARE();
2036     V_EXPECT_FALSE(got_load_start_[frame_number]);
2037     V_EXPECT_FALSE(got_load_end_[frame_number]);
2038 
2039     // Notification should be received for parent frame before child frame.
2040     if (frame_number == 0) {
2041       V_EXPECT_FALSE(got_load_start_[1]);
2042       V_EXPECT_FALSE(got_load_start_[2]);
2043       V_EXPECT_FALSE(got_load_start_[3]);
2044     } else if (frame_number == 1) {
2045       V_EXPECT_TRUE(got_load_start_[0]);
2046       V_EXPECT_FALSE(got_load_start_[2]);
2047       V_EXPECT_FALSE(got_load_start_[3]);
2048     } else if (frame_number == 2) {
2049       V_EXPECT_TRUE(got_load_start_[0]);
2050       V_EXPECT_TRUE(got_load_start_[1]);
2051       V_EXPECT_FALSE(got_load_start_[3]);
2052     } else if (frame_number == 3) {
2053       V_EXPECT_TRUE(got_load_start_[0]);
2054       V_EXPECT_TRUE(got_load_start_[1]);
2055       V_EXPECT_TRUE(got_load_start_[2]);
2056     }
2057 
2058     got_load_start_[frame_number].yes();
2059 
2060     V_EXPECT_TRUE(parent::OnLoadStart(browser, frame));
2061     V_RETURN();
2062   }
2063 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)2064   bool OnLoadEnd(CefRefPtr<CefBrowser> browser,
2065                  CefRefPtr<CefFrame> frame) override {
2066     const int frame_number = GetNavFromMultiNavURL(frame->GetURL());
2067 
2068     V_DECLARE();
2069     V_EXPECT_TRUE(got_load_start_[frame_number]);
2070     V_EXPECT_FALSE(got_load_end_[frame_number]);
2071 
2072     // Notification should be received for child frame before parent frame.
2073     if (frame_number == 0) {
2074       V_EXPECT_TRUE(got_load_end_[1]);
2075       V_EXPECT_TRUE(got_load_end_[2]);
2076       V_EXPECT_TRUE(got_load_end_[3]);
2077     } else if (frame_number == 1) {
2078       V_EXPECT_FALSE(got_load_end_[0]);
2079       V_EXPECT_TRUE(got_load_end_[2]);
2080       V_EXPECT_TRUE(got_load_end_[3]);
2081     } else if (frame_number == 2) {
2082       V_EXPECT_FALSE(got_load_end_[0]);
2083       V_EXPECT_FALSE(got_load_end_[1]);
2084       V_EXPECT_TRUE(got_load_end_[3]);
2085     } else if (frame_number == 3) {
2086       V_EXPECT_FALSE(got_load_end_[0]);
2087       V_EXPECT_FALSE(got_load_end_[1]);
2088       V_EXPECT_FALSE(got_load_end_[2]);
2089     }
2090 
2091     V_EXPECT_TRUE(VerifyBrowserIframe(browser, frame, origin_, frame_number))
2092         << "frame_number = " << frame_number;
2093 
2094     got_load_end_[frame_number].yes();
2095 
2096     V_EXPECT_TRUE(parent::OnLoadEnd(browser, frame));
2097     V_RETURN();
2098   }
2099 
Finalize()2100   bool Finalize() override {
2101     V_DECLARE();
2102     V_EXPECT_TRUE(got_load_state_change_done_);
2103     V_EXPECT_TRUE(got_load_start_[0]);
2104     V_EXPECT_TRUE(got_load_start_[1]);
2105     V_EXPECT_TRUE(got_load_start_[2]);
2106     V_EXPECT_TRUE(got_load_start_[3]);
2107     V_EXPECT_TRUE(got_load_end_[0]);
2108     V_EXPECT_TRUE(got_load_end_[1]);
2109     V_EXPECT_TRUE(got_load_end_[2]);
2110     V_EXPECT_TRUE(got_load_end_[3]);
2111     V_EXPECT_TRUE(parent::Finalize());
2112     V_RETURN();
2113   }
2114 
2115  private:
2116   std::string origin_;
2117 
2118   TrackCallback got_load_state_change_done_;
2119   TrackCallback got_load_start_[4];
2120   TrackCallback got_load_end_[4];
2121 };
2122 
2123 class FrameNavExpectationsFactoryBrowserTestNestedIframesSameOrigin
2124     : public FrameNavExpectationsFactoryBrowser {
2125  public:
FrameNavExpectationsFactoryBrowserTestNestedIframesSameOrigin()2126   FrameNavExpectationsFactoryBrowserTestNestedIframesSameOrigin()
2127       : create_count_(0) {}
2128 
GetID() const2129   FrameNavFactoryId GetID() const override {
2130     return FNF_ID_NESTED_IFRAMES_SAME_ORIGIN;
2131   }
2132 
HasMoreNavigations() const2133   bool HasMoreNavigations() const override {
2134     return (create_count_ < kMaxMultiNavNavigations);
2135   }
2136 
Finalize()2137   bool Finalize() override {
2138     V_DECLARE();
2139     V_EXPECT_TRUE(create_count_ == kMaxMultiNavNavigations);
2140     V_RETURN();
2141   }
2142 
2143  protected:
Create(int nav)2144   std::unique_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
2145     create_count_++;
2146     return std::make_unique<FrameNavExpectationsBrowserTestNestedIframes>(nav,
2147                                                                           true);
2148   }
2149 
2150  private:
2151   int create_count_;
2152 };
2153 
2154 class FrameNavExpectationsFactoryRendererTestNestedIframesSameOrigin
2155     : public FrameNavExpectationsFactoryRenderer {
2156  public:
FrameNavExpectationsFactoryRendererTestNestedIframesSameOrigin()2157   FrameNavExpectationsFactoryRendererTestNestedIframesSameOrigin() {}
2158 
GetID() const2159   FrameNavFactoryId GetID() const override {
2160     return FNF_ID_NESTED_IFRAMES_SAME_ORIGIN;
2161   }
2162 
2163  protected:
Create(int nav)2164   std::unique_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
2165     return std::make_unique<FrameNavExpectationsRendererTestNestedIframes>(
2166         nav, true);
2167   }
2168 };
2169 
2170 }  // namespace
2171 
2172 // Test that nested iframes work.
2173 FRAME_TEST(NestedIframesSameOrigin, FNF_ID_NESTED_IFRAMES_SAME_ORIGIN)
2174 
2175 namespace {
2176 
2177 class FrameNavExpectationsFactoryBrowserTestNestedIframesDiffOrigin
2178     : public FrameNavExpectationsFactoryBrowser {
2179  public:
FrameNavExpectationsFactoryBrowserTestNestedIframesDiffOrigin()2180   FrameNavExpectationsFactoryBrowserTestNestedIframesDiffOrigin()
2181       : create_count_(0) {}
2182 
GetID() const2183   FrameNavFactoryId GetID() const override {
2184     return FNF_ID_NESTED_IFRAMES_DIFF_ORIGIN;
2185   }
2186 
HasMoreNavigations() const2187   bool HasMoreNavigations() const override {
2188     return (create_count_ < kMaxMultiNavNavigations);
2189   }
2190 
Finalize()2191   bool Finalize() override {
2192     V_DECLARE();
2193     V_EXPECT_TRUE(create_count_ == kMaxMultiNavNavigations);
2194     V_RETURN();
2195   }
2196 
2197  protected:
Create(int nav)2198   std::unique_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
2199     create_count_++;
2200     return std::make_unique<FrameNavExpectationsBrowserTestNestedIframes>(
2201         nav, false);
2202   }
2203 
2204  private:
2205   int create_count_;
2206 };
2207 
2208 class FrameNavExpectationsFactoryRendererTestNestedIframesDiffOrigin
2209     : public FrameNavExpectationsFactoryRenderer {
2210  public:
FrameNavExpectationsFactoryRendererTestNestedIframesDiffOrigin()2211   FrameNavExpectationsFactoryRendererTestNestedIframesDiffOrigin() {}
2212 
GetID() const2213   FrameNavFactoryId GetID() const override {
2214     return FNF_ID_NESTED_IFRAMES_DIFF_ORIGIN;
2215   }
2216 
2217  protected:
Create(int nav)2218   std::unique_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
2219     return std::make_unique<FrameNavExpectationsRendererTestNestedIframes>(
2220         nav, false);
2221   }
2222 };
2223 
2224 }  // namespace
2225 
2226 // Test that nested iframes work.
2227 FRAME_TEST(NestedIframesDiffOrigin, FNF_ID_NESTED_IFRAMES_DIFF_ORIGIN)
2228 
2229 namespace {
2230 
2231 // Returns a new factory in the browser or renderer process. All factory types
2232 // must be listed here.
2233 
2234 // static
2235 std::unique_ptr<FrameNavExpectationsFactoryBrowser>
FromID(FrameNavFactoryId id)2236 FrameNavExpectationsFactoryBrowser::FromID(FrameNavFactoryId id) {
2237   std::unique_ptr<FrameNavExpectationsFactoryBrowser> factory;
2238   switch (id) {
2239     case FNF_ID_SINGLE_NAV_HARNESS:
2240       factory.reset(new FrameNavExpectationsFactoryBrowserTestSingleNavHarness);
2241       break;
2242     case FNF_ID_SINGLE_NAV:
2243       factory.reset(new FrameNavExpectationsFactoryBrowserTestSingleNav);
2244       break;
2245     case FNF_ID_MULTI_NAV_HARNESS:
2246       factory.reset(new FrameNavExpectationsFactoryBrowserTestMultiNavHarness);
2247       break;
2248     case FNF_ID_MULTI_NAV:
2249       factory.reset(new FrameNavExpectationsFactoryBrowserTestMultiNav);
2250       break;
2251     case FNF_ID_NESTED_IFRAMES_SAME_ORIGIN:
2252       factory.reset(
2253           new FrameNavExpectationsFactoryBrowserTestNestedIframesSameOrigin);
2254       break;
2255     case FNF_ID_NESTED_IFRAMES_DIFF_ORIGIN:
2256       factory.reset(
2257           new FrameNavExpectationsFactoryBrowserTestNestedIframesDiffOrigin);
2258       break;
2259     default:
2260       break;
2261   }
2262   EXPECT_TRUE(factory);
2263   EXPECT_EQ(id, factory->GetID());
2264   return factory;
2265 }
2266 
2267 // static
2268 std::unique_ptr<FrameNavExpectationsFactoryRenderer>
FromID(FrameNavFactoryId id)2269 FrameNavExpectationsFactoryRenderer::FromID(FrameNavFactoryId id) {
2270   std::unique_ptr<FrameNavExpectationsFactoryRenderer> factory;
2271   switch (id) {
2272     case FNF_ID_SINGLE_NAV_HARNESS:
2273       factory.reset(
2274           new FrameNavExpectationsFactoryRendererTestSingleNavHarness);
2275       break;
2276     case FNF_ID_SINGLE_NAV:
2277       factory.reset(new FrameNavExpectationsFactoryRendererTestSingleNav);
2278       break;
2279     case FNF_ID_MULTI_NAV_HARNESS:
2280       factory.reset(new FrameNavExpectationsFactoryRendererTestMultiNavHarness);
2281       break;
2282     case FNF_ID_MULTI_NAV:
2283       factory.reset(new FrameNavExpectationsFactoryRendererTestMultiNav);
2284       break;
2285     case FNF_ID_NESTED_IFRAMES_SAME_ORIGIN:
2286       factory.reset(
2287           new FrameNavExpectationsFactoryRendererTestNestedIframesSameOrigin);
2288       break;
2289     case FNF_ID_NESTED_IFRAMES_DIFF_ORIGIN:
2290       factory.reset(
2291           new FrameNavExpectationsFactoryRendererTestNestedIframesDiffOrigin);
2292       break;
2293     default:
2294       break;
2295   }
2296   EXPECT_TRUE(factory);
2297   EXPECT_EQ(id, factory->GetID());
2298   return factory;
2299 }
2300 
2301 }  // namespace
2302 
2303 // Entry point for creating frame renderer test objects.
2304 // Called from client_app_delegates.cc.
CreateFrameRendererTests(ClientAppRenderer::DelegateSet & delegates)2305 void CreateFrameRendererTests(ClientAppRenderer::DelegateSet& delegates) {
2306   delegates.insert(new FrameNavRendererTest);
2307 }
2308