1// Copyright 2018 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#import "ios/web/public/test/web_test_with_web_state.h"
6
7#include "base/ios/ios_util.h"
8#import "ios/web/public/js_messaging/web_frame.h"
9#import "ios/web/public/js_messaging/web_frames_manager.h"
10#import "ios/web/public/web_state.h"
11#include "ios/web/public/web_state_observer.h"
12#include "testing/gmock/include/gmock/gmock.h"
13
14#if !defined(__has_feature) || !__has_feature(objc_arc)
15#error "This file requires ARC support."
16#endif
17
18using testing::Truly;
19
20namespace {
21
22// Mocks WebStateObserver navigation callbacks.
23class WebStateObserverMock : public web::WebStateObserver {
24 public:
25  WebStateObserverMock() = default;
26
27  MOCK_METHOD2(WebFrameDidBecomeAvailable,
28               void(web::WebState*, web::WebFrame*));
29  MOCK_METHOD2(WebFrameWillBecomeUnavailable,
30               void(web::WebState*, web::WebFrame*));
31  void WebStateDestroyed(web::WebState* web_state) override { NOTREACHED(); }
32
33 private:
34  DISALLOW_COPY_AND_ASSIGN(WebStateObserverMock);
35};
36
37// A predicate that returns true if |frame| is a main frame.
38bool IsMainFrame(web::WebFrame* frame) {
39  return frame->IsMainFrame();
40}
41
42// Verifies that the web frame passed to the observer is the main frame.
43ACTION_P(VerifyMainWebFrame, web_state) {
44  EXPECT_EQ(web_state, arg0);
45  EXPECT_EQ(web_state->GetWebFramesManager()->GetMainWebFrame(), arg1);
46}
47
48// Verifies that the web frame passed to the observer is a child frame.
49ACTION_P(VerifyChildWebFrame, web_state) {
50  EXPECT_EQ(web_state, arg0);
51
52  web::WebFramesManager* manager = web_state->GetWebFramesManager();
53  auto frames = manager->GetAllWebFrames();
54  EXPECT_TRUE(frames.end() != std::find(frames.begin(), frames.end(), arg1));
55  EXPECT_NE(manager->GetMainWebFrame(), arg1);
56}
57}
58
59namespace web {
60
61using WebFrameWebStateObserverInttest = WebTestWithWebState;
62
63// Web frame events should be registered on HTTP navigation.
64TEST_F(WebFrameWebStateObserverInttest, SingleWebFrameHTTP) {
65  testing::StrictMock<WebStateObserverMock> observer;
66  web_state()->AddObserver(&observer);
67  EXPECT_CALL(observer, WebFrameDidBecomeAvailable(web_state(), testing::_))
68      .WillOnce(VerifyMainWebFrame(web_state()));
69  LoadHtml(@"<p></p>", GURL("http://testurl1"));
70  EXPECT_CALL(observer, WebFrameDidBecomeAvailable(web_state(), testing::_))
71      .WillOnce(VerifyMainWebFrame(web_state()));
72  EXPECT_CALL(observer, WebFrameWillBecomeUnavailable(web_state(), testing::_))
73      .WillOnce(VerifyMainWebFrame(web_state()));
74  LoadHtml(@"<p></p>", GURL("http://testurl2"));
75  web_state()->RemoveObserver(&observer);
76}
77
78// Web frame events should be registered on HTTPS navigation.
79TEST_F(WebFrameWebStateObserverInttest, SingleWebFrameHTTPS) {
80  testing::StrictMock<WebStateObserverMock> observer;
81  web_state()->AddObserver(&observer);
82  EXPECT_CALL(observer, WebFrameDidBecomeAvailable(web_state(), testing::_))
83      .WillOnce(VerifyMainWebFrame(web_state()));
84  LoadHtml(@"<p></p>", GURL("https://testurl1"));
85  EXPECT_CALL(observer, WebFrameDidBecomeAvailable(web_state(), testing::_))
86      .WillOnce(VerifyMainWebFrame(web_state()));
87  EXPECT_CALL(observer, WebFrameWillBecomeUnavailable(web_state(), testing::_))
88      .WillOnce(VerifyMainWebFrame(web_state()));
89  LoadHtml(@"<p></p>", GURL("https://testurl2"));
90  web_state()->RemoveObserver(&observer);
91}
92
93// Web frame event should be registered on HTTPS navigation with iframe.
94TEST_F(WebFrameWebStateObserverInttest, TwoWebFrameHTTPS) {
95  testing::StrictMock<WebStateObserverMock> observer;
96  web_state()->AddObserver(&observer);
97
98  // The order in which the main and child frames become available is not
99  // guaranteed due to the async nature of messaging. The following expectations
100  // use separate matchers to identify main and child frames so that they can
101  // be matched in any order.
102  EXPECT_CALL(observer,
103              WebFrameDidBecomeAvailable(web_state(), Truly(IsMainFrame)))
104      .WillOnce(VerifyMainWebFrame(web_state()));
105  EXPECT_CALL(observer,
106              WebFrameDidBecomeAvailable(web_state(), Not(Truly(IsMainFrame))))
107      .WillOnce(VerifyChildWebFrame(web_state()));
108  LoadHtml(@"<p><iframe/></p>", GURL("https://testurl1"));
109
110  EXPECT_CALL(observer,
111              WebFrameDidBecomeAvailable(web_state(), Truly(IsMainFrame)))
112      .WillOnce(VerifyMainWebFrame(web_state()));
113  EXPECT_CALL(observer,
114              WebFrameDidBecomeAvailable(web_state(), Not(Truly(IsMainFrame))))
115      .WillOnce(VerifyChildWebFrame(web_state()));
116  EXPECT_CALL(observer,
117              WebFrameWillBecomeUnavailable(web_state(), Truly(IsMainFrame)))
118      .WillOnce(VerifyMainWebFrame(web_state()));
119  EXPECT_CALL(observer, WebFrameWillBecomeUnavailable(web_state(),
120                                                      Not(Truly(IsMainFrame))))
121      .WillOnce(VerifyChildWebFrame(web_state()));
122  LoadHtml(@"<p><iframe/></p>", GURL("https://testurl2"));
123
124  web_state()->RemoveObserver(&observer);
125}
126
127}  // namespace web
128