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