File: form_unittest.mm

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (203 lines) | stat: -rw-r--r-- 7,567 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "base/apple/foundation_util.h"
#import "base/test/ios/wait_util.h"
#import "base/time/time.h"
#import "components/autofill/ios/browser/autofill_util.h"
#import "ios/web/public/js_messaging/web_view_js_utils.h"
#import "ios/web/public/test/javascript_test.h"
#import "ios/web/public/test/js_test_util.h"
#import "testing/gtest_mac.h"

using web::test::ExecuteJavaScript;

NSString* const kMessageHandlerName = @"TestHandler";

//
@interface FakeScriptMessageHandlerForFormTesting
    : NSObject <WKScriptMessageHandler>

@property(nonatomic, strong) WKScriptMessage* lastReceivedMessage;
@property(nonatomic, assign) int messageCount;

@end

@implementation FakeScriptMessageHandlerForFormTesting

- (void)userContentController:(WKUserContentController*)userContentController
      didReceiveScriptMessage:(WKScriptMessage*)message {
  _lastReceivedMessage = message;
  ++_messageCount;
}

@end

namespace autofill {

// Text fixture to test form.js.
class FormJsTest : public web::JavascriptTest {
 protected:
  FormJsTest()
      : handler_([[FakeScriptMessageHandlerForFormTesting alloc] init]) {
    // Add an handler to get messages.
    [web_view().configuration.userContentController
        addScriptMessageHandler:handler_
                           name:kMessageHandlerName];
  }

  void SetUp() override {
    web::JavascriptTest::SetUp();
    AddGCrWebScript();
    AddCommonScript();
    AddMessageScript();
    AddUserScript(@"fill");
    AddUserScript(@"form");
    AddUserScript(@"autofill_form_features");
  }

  FakeScriptMessageHandlerForFormTesting* handler_;
};

TEST_F(FormJsTest, GetIframeElements) {
  LoadHtml(@"<iframe id='frame1' srcdoc='foo'></iframe>"
           @"<p id='not-an-iframe'>"
           @"<iframe id='frame2' srcdoc='bar'></iframe>"
           @"<marquee id='definitely-not-an-iframe'>baz</marquee>"
           @"</p>");

  EXPECT_NSEQ(
      @"frame1,frame2",
      ExecuteJavaScript(
          web_view(),
          @"const frames = __gCrWeb.form.getIframeElements(document.body);"
          @"frames.map((f) => { return f.id; }).join();"));

  // Check that the return objects have a truthy contentWindow property.
  EXPECT_NSEQ(@YES,
              ExecuteJavaScript(web_view(), @"!!(frames[0].contentWindow);"));
  EXPECT_NSEQ(@YES,
              ExecuteJavaScript(web_view(), @"!!(frames[1].contentWindow);"));
}

// Tests that the `formSubmitted` handler does deduping.
TEST_F(FormJsTest, FormSubmitted_Deduping) {
  // Create arbitrary form elements to use as the submitted forms.
  LoadHtml(@"<form name='form1'></form><form name='form2'></form>");

  // Swizzle the webkit messaging posting method to count the number of messages
  // sent over. It should only concern submission messages for this test.
  NSString* swizzleScript =
      @"var gMsgCount = 0; "
       "let oldFn = UserMessageHandler.prototype.postMessage; "
       " function newFn(...args) { ++gMsgCount; return oldFn.apply(this, "
       "args); }; "
       "UserMessageHandler.prototype.postMessage = newFn";
  ExecuteJavaScript(web_view(), swizzleScript);

  // Enable form submission deduping.
  ExecuteJavaScript(web_view(), @"__gCrWeb.autofill_form_features."
                                 "setAutofillDedupeFormSubmission(true);");

  // == Submit first form ==

  // Submit the first form for the first time.
  ExecuteJavaScript(web_view(),
                    @"__gCrWeb.form.formSubmitted("
                     "document.forms[0], 'TestHandler', false, false)");

  // Wait for the submission message for the first form to be received from the
  // renderer. This verifies that the submission is at least reported once.
  {
    __block WKScriptMessage* messageFromForm;
    __weak __typeof(handler_) weak_handler = handler_;
    ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
        base::test::ios::kWaitForJSCompletionTimeout, ^bool() {
          messageFromForm = weak_handler.lastReceivedMessage;
          return weak_handler.lastReceivedMessage;
        }));
    ASSERT_TRUE(messageFromForm);
    NSDictionary* messageFromFormContent =
        base::apple::ObjCCastStrict<NSDictionary>(messageFromForm.body);
    EXPECT_NSEQ(@"form1", messageFromFormContent[@"formName"]);
  }

  // Attempt other submissions on the same form, where it should be deduped
  // this time, hence ignored.
  for (size_t i = 0; i < 4; ++i) {
    ExecuteJavaScript(web_view(),
                      @"__gCrWeb.form.formSubmitted("
                       "document.forms[0], 'TestHandler', false, false)");
  }

  // Verify that the submission message was only sent over once despite
  // triggering formSubmitted() 5 times on the same form (the first form in this
  // occurrence). Since all the scripts are run in order in the same JS event
  // loop, it is guaranteed that all formSubmitted() were made before verifying
  // the number of calls.
  EXPECT_NSEQ(@(1), ExecuteJavaScript(web_view(), @"gMsgCount"));

  handler_.lastReceivedMessage = nil;

  // == Submit other form ==

  // Submit the other form that wasn't submitted yet.
  ExecuteJavaScript(web_view(),
                    @"__gCrWeb.form.formSubmitted("
                     "document.forms[1], 'TestHandler', false, false)");

  // Wait for the submission message for the other form to be received from the
  // renderer. This verifies that the submission is at least reported once per
  // form.
  {
    __weak __typeof(handler_) weak_handler = handler_;
    __block WKScriptMessage* messageFromForm;
    ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
        base::test::ios::kWaitForJSCompletionTimeout, ^bool() {
          messageFromForm = weak_handler.lastReceivedMessage;
          return weak_handler.lastReceivedMessage;
        }));
    ASSERT_TRUE(messageFromForm);
    NSDictionary* messageFromFormContent =
        base::apple::ObjCCastStrict<NSDictionary>(messageFromForm.body);
    EXPECT_NSEQ(@"form2", messageFromFormContent[@"formName"]);
  }

  // Attempt other submissions on the same form, where it should be deduped
  // this time, hence ignored. Verify that the submission message count remains
  // 2, one message for each form.
  for (size_t i = 0; i < 4; ++i) {
    ExecuteJavaScript(web_view(),
                      @"__gCrWeb.form.formSubmitted("
                       "document.forms[1], 'TestHandler', false, false)");
  }
  EXPECT_TRUE(ExecuteJavaScript(web_view(), @"gMsgCount == 2"));
}

// Tests that the `formSubmitted` handler doesn't do deduping when the feature
// doesn't allow it.
TEST_F(FormJsTest, FormSubmitted_NoDeduping) {
  // Create an arbitrary form to used as the submitted form.
  LoadHtml(@"<form></form>");

  // Enable deduping.
  ExecuteJavaScript(web_view(), @"__gCrWeb.autofill_form_features."
                                 "setAutofillDedupeFormSubmission(false);");

  // Submit the form 4 times where each event should be reported (messaged over)
  // because there is no deduping.
  for (size_t i = 0; i < 4; ++i) {
    ExecuteJavaScript(web_view(),
                      @"__gCrWeb.form.formSubmitted("
                       "document.forms[0], 'TestHandler', false, false)");
  }

  // Wait for all submission messages to be sent over.
  ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
      base::test::ios::kWaitForJSCompletionTimeout, ^bool() {
        return handler_.messageCount == 4;
      }));
}

}  // namespace autofill