summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjoenotcharles <joenotcharles@chromium.org>2016-01-14 09:00:33 -0800
committerCommit bot <commit-bot@chromium.org>2016-01-14 17:01:29 +0000
commit46bebf29983b58a58732216a7ed5740a43024397 (patch)
tree31c901de35c19a8653f100e5dc6257d02f7ece4f
parente4071b1c232210e43a7236445f141b0e3e8acfb4 (diff)
downloadchromium_src-46bebf29983b58a58732216a7ed5740a43024397.zip
chromium_src-46bebf29983b58a58732216a7ed5740a43024397.tar.gz
chromium_src-46bebf29983b58a58732216a7ed5740a43024397.tar.bz2
Check url path as well as document title to detect formless autofill page
Autofill checks the document title on page load to decide whether input elements outside forms should be considered part of a checkout flow. Also check the path part of the url for documents without a title tag. Originally the title check used a case-insensitive regex but http://crrev.com/1419373006 replaced that with a string compare for performance. As a side effect this made the comparison case-sensitive. This patch also restores the case-insensitive title comparison. BUG=555010 Review URL: https://codereview.chromium.org/1508293006 Cr-Commit-Position: refs/heads/master@{#369436}
-rw-r--r--chrome/renderer/autofill/form_autofill_browsertest.cc175
-rw-r--r--chrome/test/data/autofill/heuristics/input/bug_555010.html282
-rw-r--r--chrome/test/data/autofill/heuristics/output/bug_555010.out22
-rw-r--r--components/autofill/content/renderer/form_autofill_util.cc71
-rw-r--r--content/public/test/render_view_test.cc99
-rw-r--r--content/public/test/render_view_test.h26
6 files changed, 615 insertions, 60 deletions
diff --git a/chrome/renderer/autofill/form_autofill_browsertest.cc b/chrome/renderer/autofill/form_autofill_browsertest.cc
index 9985fc2..c88bdc2 100644
--- a/chrome/renderer/autofill/form_autofill_browsertest.cc
+++ b/chrome/renderer/autofill/form_autofill_browsertest.cc
@@ -104,8 +104,10 @@ const char kFormHtml[] =
" <INPUT type='submit' name='reply-send' value='Send'/>"
"</FORM>";
+// This constant uses a mixed-case title tag to be sure that the title match is
+// not case-sensitive. Other tests in this file use an all-lower title tag.
const char kUnownedFormHtml[] =
- "<HEAD><TITLE>enter shipping info</TITLE></HEAD>"
+ "<HEAD><TITLE>Enter Shipping Info</TITLE></HEAD>"
"<INPUT type='text' id='firstname'/>"
"<INPUT type='text' id='lastname'/>"
"<INPUT type='hidden' id='imhidden'/>"
@@ -135,6 +137,72 @@ const char kUnownedFormHtml[] =
"<TEXTAREA id='textarea-nonempty'>Go&#10;away!</TEXTAREA>"
"<INPUT type='submit' name='reply-send' value='Send'/>";
+// This constant has no title tag, and should be passed to
+// LoadHTMLWithURLOverride to test the detection of unowned forms by URL.
+const char kUnownedUntitledFormHtml[] =
+ "<INPUT type='text' id='firstname'/>"
+ "<INPUT type='text' id='lastname'/>"
+ "<INPUT type='hidden' id='imhidden'/>"
+ "<INPUT type='text' id='notempty' value='Hi'/>"
+ "<INPUT type='text' autocomplete='off' id='noautocomplete'/>"
+ "<INPUT type='text' disabled='disabled' id='notenabled'/>"
+ "<INPUT type='text' readonly id='readonly'/>"
+ "<INPUT type='text' style='visibility: hidden'"
+ " id='invisible'/>"
+ "<INPUT type='text' style='display: none' id='displaynone'/>"
+ "<INPUT type='month' id='month'/>"
+ "<INPUT type='month' id='month-nonempty' value='2011-12'/>"
+ "<SELECT id='select'>"
+ " <OPTION></OPTION>"
+ " <OPTION value='CA'>California</OPTION>"
+ " <OPTION value='TX'>Texas</OPTION>"
+ "</SELECT>"
+ "<SELECT id='select-nonempty'>"
+ " <OPTION value='CA' selected>California</OPTION>"
+ " <OPTION value='TX'>Texas</OPTION>"
+ "</SELECT>"
+ "<SELECT id='select-unchanged'>"
+ " <OPTION value='CA' selected>California</OPTION>"
+ " <OPTION value='TX'>Texas</OPTION>"
+ "</SELECT>"
+ "<TEXTAREA id='textarea'></TEXTAREA>"
+ "<TEXTAREA id='textarea-nonempty'>Go&#10;away!</TEXTAREA>"
+ "<INPUT type='submit' name='reply-send' value='Send'/>";
+
+// This constant does not have a title tag, but should match an unowned form
+// anyway because it is not English.
+const char kUnownedNonEnglishFormHtml[] =
+ "<HTML LANG='fr'>"
+ "<INPUT type='text' id='firstname'/>"
+ "<INPUT type='text' id='lastname'/>"
+ "<INPUT type='hidden' id='imhidden'/>"
+ "<INPUT type='text' id='notempty' value='Hi'/>"
+ "<INPUT type='text' autocomplete='off' id='noautocomplete'/>"
+ "<INPUT type='text' disabled='disabled' id='notenabled'/>"
+ "<INPUT type='text' readonly id='readonly'/>"
+ "<INPUT type='text' style='visibility: hidden'"
+ " id='invisible'/>"
+ "<INPUT type='text' style='display: none' id='displaynone'/>"
+ "<INPUT type='month' id='month'/>"
+ "<INPUT type='month' id='month-nonempty' value='2011-12'/>"
+ "<SELECT id='select'>"
+ " <OPTION></OPTION>"
+ " <OPTION value='CA'>California</OPTION>"
+ " <OPTION value='TX'>Texas</OPTION>"
+ "</SELECT>"
+ "<SELECT id='select-nonempty'>"
+ " <OPTION value='CA' selected>California</OPTION>"
+ " <OPTION value='TX'>Texas</OPTION>"
+ "</SELECT>"
+ "<SELECT id='select-unchanged'>"
+ " <OPTION value='CA' selected>California</OPTION>"
+ " <OPTION value='TX'>Texas</OPTION>"
+ "</SELECT>"
+ "<TEXTAREA id='textarea'></TEXTAREA>"
+ "<TEXTAREA id='textarea-nonempty'>Go&#10;away!</TEXTAREA>"
+ "<INPUT type='submit' name='reply-send' value='Send'/>"
+ "</HTML>";
+
std::string RetrievalMethodToString(
const WebElementDescriptor::RetrievalMethod& method) {
switch (method) {
@@ -263,11 +331,15 @@ class FormAutofillTest : public ChromeRenderViewTest {
// Test FormFillxxx functions.
void TestFormFillFunctions(const char* html,
bool unowned,
+ const char* url_override,
const AutofillFieldCase* field_cases,
size_t number_of_field_cases,
FillFormFunction fill_form_function,
GetValueFunction get_value_function) {
- LoadHTML(html);
+ if (url_override)
+ LoadHTMLWithUrlOverride(html, url_override);
+ else
+ LoadHTML(html);
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
@@ -362,7 +434,7 @@ class FormAutofillTest : public ChromeRenderViewTest {
id).to<WebInputElement>();
}
- void TestFillForm(const char* html, bool unowned) {
+ void TestFillForm(const char* html, bool unowned, const char* url_override) {
static const AutofillFieldCase field_cases[] = {
// fields: form_control_type, name, initial_value, autocomplete_attribute,
// should_be_autofilled, autofill_value, expected_value
@@ -423,7 +495,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
"some multi-\nline value",
"Go\naway!"},
};
- TestFormFillFunctions(html, unowned, field_cases, arraysize(field_cases),
+ TestFormFillFunctions(html, unowned, url_override,
+ field_cases, arraysize(field_cases),
FillForm, &GetValueWrapper);
// Verify preview selection.
WebInputElement firstname = GetInputElementById("firstname");
@@ -431,7 +504,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
EXPECT_EQ(16, firstname.selectionEnd());
}
- void TestPreviewForm(const char* html, bool unowned) {
+ void TestPreviewForm(const char* html, bool unowned,
+ const char* url_override) {
static const AutofillFieldCase field_cases[] = {
// Normal empty fields should be previewed.
{"text",
@@ -495,7 +569,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
"suggested multi-\nline value",
""},
};
- TestFormFillFunctions(html, unowned, field_cases, arraysize(field_cases),
+ TestFormFillFunctions(html, unowned, url_override,
+ field_cases, arraysize(field_cases),
&PreviewForm, &GetSuggestedValueWrapper);
// Verify preview selection.
@@ -504,6 +579,20 @@ class FormAutofillTest : public ChromeRenderViewTest {
EXPECT_EQ(19, firstname.selectionEnd());
}
+ void TestUnmatchedUnownedForm(const char* html, const char* url_override) {
+ if (url_override)
+ LoadHTMLWithUrlOverride(html, url_override);
+ else
+ LoadHTML(html);
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(nullptr, web_frame);
+
+ FormCache form_cache(*web_frame);
+ std::vector<FormData> forms = form_cache.ExtractNewForms();
+ ASSERT_EQ(0U, forms.size());
+ }
+
void TestFindFormForInputElement(const char* html, bool unowned) {
LoadHTML(html);
WebFrame* web_frame = GetMainFrame();
@@ -2508,11 +2597,29 @@ TEST_F(FormAutofillTest, FindFormForTextAreaElementForUnownedForm) {
// Test regular FillForm function.
TEST_F(FormAutofillTest, FillForm) {
- TestFillForm(kFormHtml, false);
+ TestFillForm(kFormHtml, false, nullptr);
}
TEST_F(FormAutofillTest, FillFormForUnownedForm) {
- TestFillForm(kUnownedFormHtml, true);
+ TestFillForm(kUnownedFormHtml, true, nullptr);
+}
+
+TEST_F(FormAutofillTest, FillFormForUnownedUntitledForm) {
+ TestFillForm(kUnownedUntitledFormHtml, true,
+ "http://example.test/checkout_flow");
+}
+
+TEST_F(FormAutofillTest, FillFormForUnownedNonEnglishForm) {
+ TestFillForm(kUnownedNonEnglishFormHtml, true, nullptr);
+}
+
+TEST_F(FormAutofillTest, FillFormForUnownedNonASCIIForm) {
+ std::string html("<HEAD><TITLE>accented latin: \xC3\xA0, thai: \xE0\xB8\x81, "
+ "control: \x04, nbsp: \xEF\xBB\xBF, non-BMP: \xF0\x9F\x8C\x80; This "
+ "should match a CHECKOUT flow despite the non-ASCII chars"
+ "</TITLE></HEAD>");
+ html.append(kUnownedUntitledFormHtml);
+ TestFillForm(html.c_str(), true, nullptr);
}
TEST_F(FormAutofillTest, FillFormIncludingNonFocusableElements) {
@@ -2594,19 +2701,65 @@ TEST_F(FormAutofillTest, FillFormIncludingNonFocusableElements) {
"some multi-\nline value",
"some multi-\nline value"},
};
- TestFormFillFunctions(kFormHtml, false, field_cases, arraysize(field_cases),
+ TestFormFillFunctions(kFormHtml, false, nullptr,
+ field_cases, arraysize(field_cases),
&FillFormIncludingNonFocusableElementsWrapper,
&GetValueWrapper);
}
TEST_F(FormAutofillTest, PreviewForm) {
- TestPreviewForm(kFormHtml, false);
+ TestPreviewForm(kFormHtml, false, nullptr);
}
TEST_F(FormAutofillTest, PreviewFormForUnownedForm) {
- TestPreviewForm(kUnownedFormHtml, true);
+ TestPreviewForm(kUnownedFormHtml, true, nullptr);
+}
+
+TEST_F(FormAutofillTest, PreviewFormForUnownedUntitledForm) {
+ // This test uses a mixed-case URL to be sure that the url match is not
+ // case-sensitive.
+ TestPreviewForm(kUnownedUntitledFormHtml, true,
+ "http://example.test/Enter_Shipping_Address/");
+}
+
+TEST_F(FormAutofillTest, PreviewFormForUnownedNonEnglishForm) {
+ TestPreviewForm(kUnownedNonEnglishFormHtml, true, nullptr);
+}
+
+// Data that looks like an unowned form should NOT be matched unless an
+// additional indicator is present, such as title tag or url, to prevent false
+// positives.
+
+TEST_F(FormAutofillTest, UnmatchedFormNoURL) {
+ TestUnmatchedUnownedForm(kUnownedUntitledFormHtml, nullptr);
+}
+
+TEST_F(FormAutofillTest, UnmatchedFormPathWithoutKeywords) {
+ TestUnmatchedUnownedForm(kUnownedUntitledFormHtml,
+ "http://example.test/path_without_keywords");
+}
+
+TEST_F(FormAutofillTest, UnmatchedFormKeywordInQueryOnly) {
+ TestUnmatchedUnownedForm(kUnownedUntitledFormHtml,
+ "http://example.test/search?q=checkout+in+query");
}
+TEST_F(FormAutofillTest, UnmatchedFormTitleWithoutKeywords) {
+ std::string wrong_title_html(
+ "<TITLE>This title has nothing to do with autofill</TITLE>");
+ wrong_title_html += kUnownedUntitledFormHtml;
+ TestUnmatchedUnownedForm(wrong_title_html.c_str(), nullptr);
+}
+
+TEST_F(FormAutofillTest, UnmatchedFormNonASCII) {
+ std::string html("<HEAD><TITLE>Non-ASCII soft hyphen in the middle of "
+ "keyword prevents a match here: check\xC2\xADout"
+ "</TITLE></HEAD>");
+ html.append(kUnownedUntitledFormHtml);
+ TestUnmatchedUnownedForm(html.c_str(), nullptr);
+}
+
+
TEST_F(FormAutofillTest, Labels) {
ExpectJohnSmithLabels(
"<FORM name='TestForm' action='http://cnn.com' method='post'>"
diff --git a/chrome/test/data/autofill/heuristics/input/bug_555010.html b/chrome/test/data/autofill/heuristics/input/bug_555010.html
new file mode 100644
index 0000000..bf026a0
--- /dev/null
+++ b/chrome/test/data/autofill/heuristics/input/bug_555010.html
@@ -0,0 +1,282 @@
+<HTML>
+ <HEAD>
+ <meta name="viewport" content="width=320, user-scalable=no, initial-scale=1.0, maximum-scale=1.0" />
+ <meta http-equiv="x-ua-compatible" content="IE=edge" >
+ <title>Office Supplies, Technology, Ink Much More | Staples - add checkout tag because url is inaccessible from test</title>
+ <meta name="title" content="Office Supplies, Technology, Ink Much More | Staples" />
+ <meta name="description" content="Your partner for office supplies, technology and cleaning & breakroom. Discover more about Staples product range today. FREE shipping on orders over $45">
+ <meta charset="UTF-8" />
+ </HEAD>
+ <BODY style="margin:0px; padding: 0px;">
+ <div id="id_skPageContainer" class="cls_skCOPg">
+ <div id="id_skStudio_Wrapper">
+ <div id="id_scfHeader" class="scfHeader" align="center"></div>
+ <div id="studiop_31" class="scfPage skcWebPage sk-ui-layout-legacy" align="center" data-pageid="31" data-viewName = "mobile" data-pageUrl="office/supplies/StaplesCheckoutFlow" >
+ <div id="id_scfContent_" class="scfContent" align="left">
+ <div id="old_checkout" class="lyt_cont_div page" style= "width: 100%; height: 480px; " flexiPage="true">
+ <div id="skPageLayoutCell_31_id-center" class="skc_pageCellLayout cls_skWidget widget68 " widgetId = "306" widgetName = "widget68" widgetType = "6" style="width:100.0%;height:480px;float: left;position: relative; overflow: hidden;">
+ <div class="cls_richTextWidget" id=skPageLayoutCell_31_id-center >
+ <div id="id_skPageContainer">
+ <div id="id_skcontent" class="cls_skContent cls_skCntPanelClosed">
+ <div id="id_skPageContent">
+ <div class="testcheckout">
+ <div class="cls_skCOHeaderCont">
+ <div class="cls_skCOBackNav"></div>
+ <span class="cls_skManageAddrHeading cls_skHide">Manage Addresses</span>
+ <span class="cls_skEditAddrHeading cls_skHide">Edit Address</span>
+ <span class="cls_skAddAddrHeading cls_skHide">Add Address</span>
+ <span class="cls_skCOHeading cls_skHide">Checkout</span>
+ <span class="cls_skECOHeading cls_skHide">Guest Checkout</span>
+ <span class="cls_skStorePickUpHeading cls_skHide"></span>
+ <span class="cls_skAlternatePickUpHeading cls_skHide">Alternate Pick Up Person</span>
+ <span class="cls_skRCHeading cls_skHide">Returning Customer</span>
+ <span class="cls_skManageCardHeading cls_skHide">Manage Payment Methods</span>
+ <span class="cls_skEditCardHeading cls_skHide">Edit Payment Method</span>
+ <span class="cls_skAddCardHeading cls_skHide">Add Payment Method</span>
+ </div>
+ <div class="cls_skCOShippingText"></div>
+ <div class="cls_skLoginCont cls_skHide">
+ <div class="cls_skAppleSkuCOCont cls_skHide">
+ <b>Guest Checkout Not Available</b>
+ <br>Because of one or more items in your Cart, Guest Checkout is not available. Please sign in to continue.
+ </div>
+ <div class="cls_skGuestCOCont">
+ <div class="cls_skSignInCont"> Returning customer?
+ <div class="cls_skSignInBtn">SIGN IN</div>
+ </div>
+ <div class="cls_skGuestCOTxt">Guest Checkout</div>
+ <div class="cls_skClear"></div>
+ </div>
+ </div>
+ <div class="cls_skSigninWrap cls_skHide">
+ <form class="cls_skCOLogonForm">
+ <div id="id_skSigninErr" class="cls_skSigninErr"></div>
+ <div id="id_skSignInputName" class="cls_skInput">
+ <input id="id_skCOUsername" name="userName" class="cls_skInputTxt cls_skUsername scTrack scInput" sctype="scInput" scvalue="username" scinput="input" fieldtype="username" placeholder="Username or Email address" event="username field" tabindex="5" maxlength="55" autocomplete="on" autocorrect="off" autocapitalize="off" type="email">
+ <div class="cls_skClearBut"></div>
+ </div>
+ <div id="id_skSignInputPwd" class="cls_skInput">
+ <input id="id_skCOPwd" name="password" class="cls_skInputTxt cls_skPwd scTrack scInput" sctype="scInput" scvalue="password" scinput="input" fieldtype="pwd" placeholder="Password" event="password field" tabindex="5" maxlength="256" autocapitalize="off" autocomplete="on" type="password">
+ <div class="cls_skClearBut"></div>
+ </div>
+ </form>
+ <div class="cls_skForgotPwd scTrack scButton" sctype="scButton" scvalue="forgetpassword">Forgot Password?</div>
+ <div class="cls_skSignIn scTrack scButton" sctype="scButton" scvalue="Signin">Sign In</div>
+ <div class="cls_skClear"></div>
+ </div>
+ <div class="cls_skUserCont">
+ <div id="id_skCOErrorCont" class="cls_skCOErrorCont"></div>
+ <div id="id_skCOShippingCont" class="cls_skCOShippingCont cls_skHide">
+ <div id="id_skCheckoutInputCont" class="cls_skCheckoutInputCont">
+ <div id="id_skShipInputName" class="cls_skInput">
+ <input id="id_skCOName" class="cls_skInputTxt cls_skName scTrack scInput" sctype="scInput" scvalue="editname" scinput="input" fieldtype="name" placeholder="Full Name (First Name Last Name)" event="shipping name" tabindex="1" maxlength="128" name="cardName" autocomplete="on" autocorrect="off" autocapitalize="off" type="text">
+ <div class="cls_skClearBut"></div>
+ </div>
+ <div id="id_skShipInputAddress" class="cls_skInput">
+ <div class="cls_skAddressWrapper">
+ <div class="cls_skCOShipAddress cls_skAddressCont">
+ <input id="id_skCOShipAddress" class="cls_skInputTxt cls_skAddress cls_skShipToAddress scTrack scInput" sctype="scInput" scvalue="editadd" scinput="input" fieldtype="address" placeholder="Shipping Address" event="shipping address" tabindex="2" maxlength="128" addresstype="ship" type="text">
+ <div class="cls_skClearBut"></div>
+ </div>
+ <div class="cls_skCOShipAptBldg">
+ <input id="id_skCOShipAptBldg" class="cls_skInputTxt cls_skInputOptionalTxt cls_skApartment scInput" scvalue="apartment" scinput="input" fieldtype="aptbldg" placeholder="Apt/Bldg (optional)" event="shipping apt/suite" tabindex="3" maxlength="35" autocomplete="off" type="text">
+ <div class="cls_skClearBut"></div>
+ </div>
+ </div>
+ </div>
+ <div class="cls_skShipToStore cls_skHide">
+ <div class="cls_skShipToStoreDetailTxt"></div>
+ </div>
+ <div class="cls_skStorePickUpBtn cls_skHide">
+ <div class="cls_skStorePickUpBtnTxt"></div>
+ </div>
+ <div id="id_skShipInputPhone" class="cls_skInput">
+ <input id="id_skCOPhoneno" class="cls_skInputTxt cls_skCOPhoneno cls_skPhoneNo scTrack scInput" sctype="scInput" scvalue="editphone" scinput="input" maxlength="16" fieldtype="phnumber" placeholder="Phone" event="shipping phone number" tabindex="4" autocomplete="off" type="tel">
+ <div class="cls_skClearBut"></div>
+ </div>
+ <div id="id_skShipInputEmail" class="cls_skInput">
+ <input id="id_skCOEmail" class="cls_skInputTxt cls_skEmail scTrack scInput" sctype="scInput" scvalue="email" scinput="input" fieldtype="email" placeholder="Email" event="shipping email" tabindex="5" maxlength="256" autocapitalize="off" type="email">
+ <div class="cls_skClearBut"></div>
+ </div>
+ <div id="id_skShipInputCredit" class="cls_skInput">
+ <div class="cls_skAddressWrapper">
+ <div class="cls_skCrditCarDetailsCont">Credit Card Details</div>
+ <div class="cls_skCrditCardImg"></div>
+ <div class="cls_skCOCreditCardCont">
+ <label class="cls_skAstrickSymbol">*</label>
+ <input id="id_skCOCreditCard" class="cls_skInputTxt cls_skCreditCardNo cls_skCreditCard scTrack scInput" sctype="scInput" scvalue="creditcard" scinput="input" maxlength="19" fieldtype="cardNumber" event="card number" placeholder="1234 5647 8901 2345" tabindex="6" name="cardNumber" autocomplete="off" type="tel">
+ </div>
+ <div class="cls_skCOCreditYrMnthCont">
+ <input class="cls_skInputTxt cls_skCreditYrMth cls_skCreditCard scInput" scvalue="month/year" scinput="input" fieldtype="mnthYr" placeholder="EXP" event="expire month/year" tabindex="7" name="expirationMonth" autocomplete="off" type="tel">
+ </div>
+ <div class="cls_skCOCreditCcv">
+ <input class="cls_skInputTxt cls_skCreditCcv cls_skCreditCard scInput" scvalue="CVV" scinput="input" maxlength="4" fieldtype="cvv" placeholder="CVV" event="card id" tabindex="8" name="cvv" autocomplete="off" type="tel">
+ </div>
+ <div class="cls_skClearBut"></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="cls_skCOSaveCCCont cls_skHide"> Save credit card
+ <div class="cls_skCOSaveCCtoggleCont">
+ <div class="cls_skCOSaveCCtoggleYes scTrack scOption" sctype="scOption" and="" scvalue="No|Yes"></div>
+ <div class="cls_skCOSaveCCtoggleNo scTrack scOption" sctype="scOption" and="" scvalue="No|Yes"></div>
+ </div>
+ </div>
+ <div class="cls_skCOUseAsCont cls_skHide"> Use<span></span>&nbsp;as billing address
+ <div class="cls_skCOUseAstoggleCont">
+ <div class="cls_skCOUseAstoggleYes scTrack scOption" sctype="scOption" and="" scvalue="No|Yes"></div>
+ <div class="cls_skCOUseAstoggleNo scTrack scOption" sctype="scOption" and="" scvalue="No|Yes"></div>
+ </div>
+ </div>
+ <div id="id_skCOBillingCont" class="cls_skCOBillingCont cls_skHide">
+ <div id="id_skCheckoutInputCont" class="cls_skCheckoutInputCont">
+ <div id="id_skBillInputName" class="cls_skInput">
+ <input id="id_skCOName" class="cls_skInputTxt cls_skName scTrack scInput" sctype="scInput" scvalue="bname" scinput="input" fieldtype="name" placeholder="Card Holder Name" event="billing name" tabindex="9" maxlength="128" autocomplete="on" autocorrect="off" autocapitalize="off" type="text">
+ <div class="cls_skClearBut"></div>
+ </div>
+ <div id="id_skBillInputAddress" class="cls_skInput">
+ <div class="cls_skAddressWrapper">
+ <div class="cls_skCOShipAddress cls_skAddressCont">
+ <input id="id_skCOShipAddress" class="cls_skInputTxt cls_skAddress cls_skBillToAddress scTrack scInput" sctype="scInput" scvalue="baddress" scinput="input" fieldtype="address" placeholder="Billing Address" event="billing address" tabindex="10" maxlength="128" autocomplete="off" type="text">
+ <div class="cls_skClearBut"></div>
+ </div>
+ <div class="cls_skCOShipAptBldg">
+ <input id="id_skCOShipAptBldg" class="cls_skInputTxt cls_skInputOptionalTxt cls_skApartment scInput" scvalue="apartment" scinput="input" fieldtype="aptbldg" placeholder="Apt/Bldg (optional)" event="billing apt/suite" tabindex="11" maxlength="35" autocomplete="off" type="text">
+ <div class="cls_skClearBut"></div>
+ </div>
+ </div>
+ </div>
+ <div id="id_skBillInputPhone" class="cls_skInput">
+ <input id="id_skCOPhoneno" class="cls_skInputTxt cls_skCOPhoneno cls_skPhoneNo scTrack scInput" sctype="scInput" scvalue="bphone" scinput="input" maxlength="16" fieldtype="phnumber" placeholder="Phone" event="billing phone number" tabindex="12" type="tel">
+ <div class="cls_skClearBut"></div>
+ </div>
+ </div>
+ </div>
+ <div id="id_skCartCouponsCont" class="cls_skCartCouponsCont cls_skHide"></div>
+ <div id="id_skSavedAddrWrap" class="cls_skHide">
+ <div id="id_skSavedAddrCont" class="cls_skSavedAddrCont">
+ </div>
+ </div>
+ <div id="id_skAddrWrap" class="cls_skHide">
+ <div id="id_skAddrCont" class="cls_skAddrCont">
+ <div id="id_skCheckoutInputCont" class="cls_skCheckoutInputCont">
+ <div class="cls_skInput">
+ <input id="id_skCOName" class="cls_skInputTxt cls_skName scTrack scInput" scvalue="name" scinput="input" fieldtype="name" placeholder="Name" event="shipping name" tabindex="9" maxlength="128" autocomplete="on" autocorrect="off" autocapitalize="off" type="text">
+ <div class="cls_skClearBut"></div>
+ </div>
+ <div class="cls_skInput">
+ <div class="cls_skCOShipAddress cls_skAddressCont">
+ <input id="id_skCOShipAddress" class="cls_skInputTxt cls_skAddress scTrack scInput" scvalue="address" scinput="input" fieldtype="address" placeholder="Address" event="shipping address" tabindex="10" maxlength="128" autocomplete="off" type="text">
+ <div class="cls_skClearBut"></div>
+ </div>
+ <div class="cls_skCOShipAptBldg">
+ <input id="id_skCOShipAptBldg" class="cls_skInputTxt cls_skInputOptionalTxt cls_skApartment scInput" scvalue="apartment" scinput="input" fieldtype="aptbldg" placeholder="Apt/Bldg (optional)" event="shipping apt/suite" tabindex="11" maxlength="35" autocomplete="off" type="text">
+ <div class="cls_skClearBut"></div>
+ </div>
+ </div>
+ <div class="cls_skInput">
+ <input id="id_skCOPhoneno" class="cls_skInputTxt cls_skCOPhoneno cls_skPhoneNo scTrack scInput" scvalue="phone" scinput="input" maxlength="16" fieldtype="phnumber" placeholder="Phone" event="shipping phone number" tabindex="12" type="tel">
+ <div class="cls_skClearBut"></div>
+ </div>
+ </div>
+ <div class="cls_skShipToAddr cls_skHide scTrack scButton" sctype="scButton" scvalue="shiptoaddress">SHIP TO THIS ADDRESS</div>
+ <div class="cls_skNewAddrContinue cls_skHide">CONTINUE</div>
+ </div>
+ </div>
+ <div id="id_skSavedCardWrap" class="cls_skHide">
+ <div id="id_skSavedCardCont" class="cls_skSavedCardCont"></div>
+ </div>
+ <div id="id_skCardWrap" class="cls_skHide">
+ <div id="id_skCardCont" class="cls_skCardCont">
+ <div id="id_skManageCardInputCont" class="cls_skCheckoutInputCont">
+ <div id="id_skManageInputCredit" class="cls_skInput">
+ <div class="cls_skCrditCarDetailsCont">Credit Card Details</div>
+ <div class="cls_skCrditCardImg"></div>
+ <div class="cls_skCOCreditCardCont">
+ <label class="cls_skAstrickSymbol">*</label>
+ <input id="id_skManageCreditCard" class="cls_skInputTxt cls_skCreditCardNo cls_skCreditCard scTrack scInput" scvalue="editcardno" scinput="input" maxlength="19" fieldtype="cardNumber" placeholder="1234 5647 8901 2345" tabindex="6" name="cardNumber" autocomplete="off" type="tel">
+ </div>
+ <div class="cls_skCOCreditYrMnthCont">
+ <input class="cls_skInputTxt cls_skCreditYrMth cls_skCreditCard scInput" scvalue="month/year" scinput="input" fieldtype="mnthYr" placeholder="EXP" tabindex="7" name="expirationMonth" autocomplete="off" type="tel">
+ </div>
+ <div class="cls_skCOCreditCcv">
+ <input class="cls_skInputTxt cls_skCreditCcv cls_skCreditCard scInput" scvalue="CVV" scinput="input" maxlength="4" fieldtype="cvv" placeholder="CVV" tabindex="8" name="cvv" autocomplete="off" type="tel">
+ </div>
+ <div class="cls_skClearBut"></div>
+ </div>
+ </div>
+ <div class="cls_skPayBtn cls_skHide scTrack scButton" sctype="scButton" scvalue="selectthiscard">SELECT THIS CARD</div>
+ <div class="cls_skNewCardContinue cls_skHide scTrack scButton" sctype="scButton" scvalue="addcard">ADD CARD</div>
+ </div>
+ </div>
+ <div id="id_skStorePickUpWrap" class="cls_skStorePickUpWrap cls_skHide">
+ <div class="cls_skCOaccContainer"></div>
+ </div>
+ <div id="id_skAltPickUpWrap" class="cls_skAltPickUpWrap cls_skHide">
+ <div class="cls_skStorePickupAlternateCont">
+ <div id="id_skAltPUInputPhone" class="cls_skInput">
+ <input id="id_skAltPUName" class="cls_skInputTxt cls_skName scInput" scvalue="name" scinput="input" fieldtype="name" placeholder="Name" tabindex="1" maxlength="128" autocomplete="on" autocorrect="off" autocapitalize="off" type="text">
+ <div class="cls_skClearBut"></div>
+ </div>
+ <div id="id_skAltPUInputPhone" class="cls_skInput">
+ <input id="id_skAltPUPhoneno" class="cls_skInputTxt cls_skCOPhoneno cls_skPhoneNo scInput" scvalue="phone" scinput="input" maxlength="16" fieldtype="phnumber" placeholder="Phone" tabindex="2" autocomplete="off" type="tel">
+ <div class="cls_skClearBut"></div>
+ </div>
+ <div id="id_skAltPUInputEmail" class="cls_skInput">
+ <input id="id_skAltPUEmail" class="cls_skInputTxt cls_skEmail scInput" scvalue="email" scinput="input" fieldtype="email" placeholder="Email" tabindex="3" maxlength="256" autocapitalize="off" type="email">
+ <div class="cls_skClearBut"></div>
+ </div>
+ <div class="cls_skAlternatePickupContinue">CONTINUE</div>
+ </div>
+ </div>
+ <div class="cls_skCheckoutVme cls_skHide">
+ <div class="cls_skVmeErrorMsg hide"></div>
+ <div class="cls_skCardImg"></div>
+ </div>
+ </div>
+ </div>
+ <div class="cls_skCOOrderCont cls_skHide">
+ <div class="cls_skCOOrderItemsCont">
+ <div class="cls_skCOItems cls_skCODetails"> Product Total <b>$0.00</b></div>
+ <div class="cls_skCOShipping cls_skCODetails"> Shipping <b>Free</b></div>
+ <div class="cls_skCOOversize cls_skCODetails"> Oversize Shipping Fees <b>$0.00</b></div>
+ <div class="cls_skCOCoupons cls_skCODetails"> Coupons&nbsp;&amp;&nbsp;Rewards <b>$0.00</b></div>
+ <div class="cls_skCOTax cls_skCODetails"> Estimated Tax <b>$0.00</b></div>
+ <div class="cls_skCOTotalCost cls_skCOTotAmt cls_skCODetails"> Total Amount Due <span>$0.00</span></div>
+ </div>
+ <div class="cls_skCOPayCont">
+ <div class="cls_skCOPayNow scTrack scPay" sctype="scPay" tabindex="13">PLACE ORDER</div>
+ <div class="cls_skCOPayNowLoading">
+ <div class="cls_skActivitySpinner"></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id="id_skTaxCalculationPopup" class="cls_skTaxCalculationPopup">
+ <div class="cls_skTaxCalculationCont">
+ <div class="cls_skLoadingImg"></div>
+ <div class="cls_skTaxCalculationMsg">Calculating Tax</div>
+ </div>
+ </div>
+ <div id="id_skMFLoadingGauge" class="cls_skPageLoadingGauge">
+ <div class="cls_skActivitySpinner"></div>
+ </div>
+ <div id="id_skPanelCntWrap" class="cls_skPanelCntWrap"></div>
+ <div class="cls_skCORPValidationPopup"></div>
+ <div class="cls_skVPopupTop"></div>
+ <div id="id_skHeightEl" class="cls_skHeightEl" style="display:none"></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id="id_scfFooter" class="scfFooter"></div>
+ </div>
+ </div>
+ <div class="cls_skCouponCont"></div>
+ <div class="cls_skATBPopupMask"></div>
+ </BODY>
+</HTML>
diff --git a/chrome/test/data/autofill/heuristics/output/bug_555010.out b/chrome/test/data/autofill/heuristics/output/bug_555010.out
new file mode 100644
index 0000000..32a2019
--- /dev/null
+++ b/chrome/test/data/autofill/heuristics/output/bug_555010.out
@@ -0,0 +1,22 @@
+CREDIT_CARD_NAME | cardName | Full Name (First Name Last Name) | | cardName_1-cc
+ADDRESS_HOME_LINE1 | id_skCOShipAddress | Shipping Address | | cardName_1-default
+UNKNOWN_TYPE | id_skCOShipAptBldg | Apt/Bldg (optional) | | cardName_1-default
+PHONE_HOME_WHOLE_NUMBER | id_skCOPhoneno | Phone | | cardName_1-default
+EMAIL_ADDRESS | id_skCOEmail | Email | | cardName_1-default
+CREDIT_CARD_NUMBER | cardNumber | 1234 5647 8901 2345 | | cardName_1-cc
+CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR | expirationMonth | EXP | | cardName_1-cc
+CREDIT_CARD_VERIFICATION_CODE | cvv | CVV | | cardName_1-cc
+CREDIT_CARD_NAME | id_skCOName | Card Holder Name | | id_skCOName_1-cc
+ADDRESS_HOME_LINE1 | id_skCOShipAddress | Billing Address | | id_skCOName_1-default
+UNKNOWN_TYPE | id_skCOShipAptBldg | Apt/Bldg (optional) | | id_skCOName_1-default
+PHONE_HOME_WHOLE_NUMBER | id_skCOPhoneno | Phone | | id_skCOName_1-default
+NAME_FULL | id_skCOName | Name | | id_skCOName_1-default
+ADDRESS_HOME_LINE1 | id_skCOShipAddress | Address | | id_skCOShipAddress_3-default
+UNKNOWN_TYPE | id_skCOShipAptBldg | Apt/Bldg (optional) | | id_skCOShipAddress_3-default
+PHONE_HOME_WHOLE_NUMBER | id_skCOPhoneno | Phone | | id_skCOShipAddress_3-default
+CREDIT_CARD_NUMBER | cardNumber | 1234 5647 8901 2345 | | id_skCOShipAddress_3-cc
+CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR | expirationMonth | EXP | | id_skCOShipAddress_3-cc
+CREDIT_CARD_VERIFICATION_CODE | cvv | CVV | | id_skCOShipAddress_3-cc
+CREDIT_CARD_NAME | id_skAltPUName | Name | | id_skCOShipAddress_3-cc
+PHONE_HOME_WHOLE_NUMBER | id_skAltPUPhoneno | Phone | | id_skCOShipAddress_3-default
+EMAIL_ADDRESS | id_skAltPUEmail | Email | | id_skCOShipAddress_3-default
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc
index b7bb401..40fbb03 100644
--- a/components/autofill/content/renderer/form_autofill_util.cc
+++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -1468,40 +1468,57 @@ bool UnownedCheckoutFormElementsAndFieldSetsToFormData(
FormFieldData* field) {
// Only attempt formless Autofill on checkout flows. This avoids the many
// false positives found on the non-checkout web. See
- // http://crbug.com/462375. For now this early abort only applies to
- // English-language pages, because the regex is not translated. Note that
- // an empty "lang" attribute counts as English. A potential problem is that
- // this only checks document.title(), but should actually check the main
- // frame's title. Thus it may make bad decisions for iframes.
+ // http://crbug.com/462375.
WebElement html_element = document.documentElement();
+
+ // For now this restriction only applies to English-language pages, because
+ // the keywords are not translated. Note that an empty "lang" attribute
+ // counts as English.
std::string lang;
if (!html_element.isNull())
lang = html_element.getAttribute("lang").utf8();
- if (lang.empty() ||
- base::StartsWith(lang, "en", base::CompareCase::INSENSITIVE_ASCII)) {
- std::string title(base::UTF16ToUTF8(base::string16(document.title())));
- const char* const kKeywords[] = {
- "payment",
- "checkout",
- "address",
- "delivery",
- "shipping",
- };
-
- bool found = false;
- for (const auto& keyword : kKeywords) {
- if (title.find(keyword) != base::string16::npos) {
- found = true;
- break;
- }
+ if (!lang.empty() &&
+ !base::StartsWith(lang, "en", base::CompareCase::INSENSITIVE_ASCII)) {
+ return UnownedFormElementsAndFieldSetsToFormData(
+ fieldsets, control_elements, element, document, extract_mask, form,
+ field);
+ }
+
+ // A potential problem is that this only checks document.title(), but should
+ // actually check the main frame's title. Thus it may make bad decisions for
+ // iframes.
+ base::string16 title(base::ToLowerASCII(base::string16(document.title())));
+
+ // Don't check the path for url's without a standard format path component,
+ // such as data:.
+ std::string path;
+ GURL url(document.url());
+ if (url.IsStandard())
+ path = base::ToLowerASCII(url.path());
+
+ const char* const kKeywords[] = {
+ "payment",
+ "checkout",
+ "address",
+ "delivery",
+ "shipping",
+ };
+
+ for (const auto& keyword : kKeywords) {
+ // Compare char16 elements of |title| with char elements of |keyword| using
+ // operator==.
+ auto title_pos = std::search(title.begin(), title.end(),
+ keyword, keyword + strlen(keyword));
+ if (title_pos != title.end() ||
+ path.find(keyword) != std::string::npos) {
+ // Found a keyword: treat this as an unowned form.
+ return UnownedFormElementsAndFieldSetsToFormData(
+ fieldsets, control_elements, element, document, extract_mask, form,
+ field);
}
- if (!found)
- return false;
}
- return UnownedFormElementsAndFieldSetsToFormData(
- fieldsets, control_elements, element, document, extract_mask, form,
- field);
+ return false;
}
bool UnownedPasswordFormElementsAndFieldSetsToFormData(
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index 3eabdb9..c17e342 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -36,6 +36,7 @@
#include "content/test/test_content_client.h"
#include "content/test/test_render_frame.h"
#include "third_party/WebKit/public/platform/WebScreenInfo.h"
+#include "third_party/WebKit/public/platform/WebURLLoader.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebHistoryItem.h"
@@ -64,6 +65,7 @@ using blink::WebLocalFrame;
using blink::WebMouseEvent;
using blink::WebScriptSource;
using blink::WebString;
+using blink::WebURLLoader;
using blink::WebURLRequest;
namespace {
@@ -104,37 +106,102 @@ bool GetWindowsKeyCode(char ascii_character, int* key_code) {
}
}
+WebURLRequest createDataRequest(const std::string& html) {
+ std::string url_str = "data:text/html;charset=utf-8,";
+ url_str.append(html);
+ GURL url(url_str);
+ WebURLRequest request(url);
+ request.setCheckForBrowserSideNavigation(false);
+ return request;
+}
+
} // namespace
namespace content {
-class RendererBlinkPlatformImplNoSandboxImpl
+const char kWrappedHTMLDataHeader[] = "X-WrappedHTMLData";
+
+// This loader checks all requests for the presence of the X-WrappedHTMLData
+// header and, if it's found, substitutes a data: url with the header's value
+// instead of loading the original request. It is used to implement
+// LoadHTMLWithURLOverride.
+class WebURLLoaderWrapper : public WebURLLoader {
+public:
+ WebURLLoaderWrapper(WebURLLoader* wrapped_loader)
+ : wrapped_loader_(wrapped_loader) { }
+
+ void loadSynchronously(const WebURLRequest& request,
+ blink::WebURLResponse& response,
+ blink::WebURLError& error,
+ blink::WebData& data) override {
+ std::string html = request.httpHeaderField(kWrappedHTMLDataHeader).utf8();
+ wrapped_loader_->loadSynchronously(
+ html.empty() ? request : createDataRequest(html),
+ response,
+ error,
+ data);
+ }
+
+ void loadAsynchronously(const WebURLRequest& request,
+ blink::WebURLLoaderClient* client) override {
+ std::string html = request.httpHeaderField(kWrappedHTMLDataHeader).utf8();
+ wrapped_loader_->loadAsynchronously(
+ html.empty() ? request : createDataRequest(html),
+ client);
+ }
+
+ void cancel() override {
+ wrapped_loader_->cancel();
+ }
+
+ void setDefersLoading(bool defer) override {
+ wrapped_loader_->setDefersLoading(defer);
+ }
+
+ void setLoadingTaskRunner(blink::WebTaskRunner* runner) override {
+ wrapped_loader_->setLoadingTaskRunner(runner);
+ }
+
+private:
+ std::unique_ptr<WebURLLoader> wrapped_loader_;
+};
+
+class RendererBlinkPlatformImplTestOverrideImpl
: public RendererBlinkPlatformImpl {
public:
- RendererBlinkPlatformImplNoSandboxImpl(
+ RendererBlinkPlatformImplTestOverrideImpl(
scheduler::RendererScheduler* scheduler)
: RendererBlinkPlatformImpl(scheduler) {}
+ // Get rid of the dependency to the sandbox, which is not available in
+ // RenderViewTest.
blink::WebSandboxSupport* sandboxSupport() override { return NULL; }
+
+ // Inject a WebURLLoader which rewrites requests that have the
+ // X-WrappedHTMLData header.
+ WebURLLoader* createURLLoader() override {
+ return new WebURLLoaderWrapper(
+ RendererBlinkPlatformImpl::createURLLoader());
+ }
};
-RenderViewTest::RendererBlinkPlatformImplNoSandbox::
- RendererBlinkPlatformImplNoSandbox() {
+RenderViewTest::RendererBlinkPlatformImplTestOverride::
+ RendererBlinkPlatformImplTestOverride() {
renderer_scheduler_ = scheduler::RendererScheduler::Create();
blink_platform_impl_.reset(
- new RendererBlinkPlatformImplNoSandboxImpl(renderer_scheduler_.get()));
+ new RendererBlinkPlatformImplTestOverrideImpl(renderer_scheduler_.get()));
}
-RenderViewTest::RendererBlinkPlatformImplNoSandbox::
- ~RendererBlinkPlatformImplNoSandbox() {
+RenderViewTest::RendererBlinkPlatformImplTestOverride::
+ ~RendererBlinkPlatformImplTestOverride() {
}
blink::Platform*
- RenderViewTest::RendererBlinkPlatformImplNoSandbox::Get() const {
+ RenderViewTest::RendererBlinkPlatformImplTestOverride::Get() const {
return blink_platform_impl_.get();
}
-void RenderViewTest::RendererBlinkPlatformImplNoSandbox::Shutdown() {
+void RenderViewTest::RendererBlinkPlatformImplTestOverride::Shutdown() {
renderer_scheduler_->Shutdown();
blink_platform_impl_->Shutdown();
}
@@ -177,11 +244,19 @@ bool RenderViewTest::ExecuteJavaScriptAndReturnIntValue(
}
void RenderViewTest::LoadHTML(const char* html) {
- std::string url_str = "data:text/html;charset=utf-8,";
- url_str.append(html);
- GURL url(url_str);
+ GetMainFrame()->loadRequest(createDataRequest(html));
+ // The load actually happens asynchronously, so we pump messages to process
+ // the pending continuation.
+ FrameLoadWaiter(view_->GetMainRenderFrame()).Wait();
+}
+
+void RenderViewTest::LoadHTMLWithUrlOverride(const char* html,
+ const char* url_override) {
+ GURL url(url_override);
WebURLRequest request(url);
request.setCheckForBrowserSideNavigation(false);
+ request.addHTTPHeaderField(kWrappedHTMLDataHeader, WebString::fromUTF8(html));
+
GetMainFrame()->loadRequest(request);
// The load actually happens asynchronously, so we pump messages to process
// the pending continuation.
diff --git a/content/public/test/render_view_test.h b/content/public/test/render_view_test.h
index 27cea17..6e351de 100644
--- a/content/public/test/render_view_test.h
+++ b/content/public/test/render_view_test.h
@@ -48,23 +48,23 @@ class FakeCompositorDependencies;
class MockRenderProcess;
class PageState;
class RendererMainPlatformDelegate;
-class RendererBlinkPlatformImplNoSandboxImpl;
+class RendererBlinkPlatformImplTestOverrideImpl;
class RenderView;
class RenderViewTest : public testing::Test, blink::WebLeakDetectorClient {
public:
- // A special BlinkPlatformImpl class for getting rid off the dependency to the
- // sandbox, which is not available in RenderViewTest.
- class RendererBlinkPlatformImplNoSandbox {
+ // A special BlinkPlatformImpl class with overrides that are useful for
+ // RenderViewTest.
+ class RendererBlinkPlatformImplTestOverride {
public:
- RendererBlinkPlatformImplNoSandbox();
- ~RendererBlinkPlatformImplNoSandbox();
+ RendererBlinkPlatformImplTestOverride();
+ ~RendererBlinkPlatformImplTestOverride();
blink::Platform* Get() const;
void Shutdown();
private:
scoped_ptr<scheduler::RendererScheduler> renderer_scheduler_;
- scoped_ptr<RendererBlinkPlatformImplNoSandboxImpl> blink_platform_impl_;
+ scoped_ptr<RendererBlinkPlatformImplTestOverrideImpl> blink_platform_impl_;
};
RenderViewTest();
@@ -88,10 +88,16 @@ class RenderViewTest : public testing::Test, blink::WebLeakDetectorClient {
bool ExecuteJavaScriptAndReturnIntValue(const base::string16& script,
int* result);
- // Loads the given HTML into the main frame as a data: URL and blocks until
- // the navigation is committed.
+ // Loads |html| into the main frame as a data: URL and blocks until the
+ // navigation is committed.
void LoadHTML(const char* html);
+ // Pretends to load |url| into the main frame, but substitutes |html| for the
+ // response body (and does not include any response headers). This can be used
+ // instead of LoadHTML for tests that cannot use a data: url (for example if
+ // document.location needs to be set to something specific.)
+ void LoadHTMLWithUrlOverride(const char* html, const char* url);
+
// Returns the current PageState.
// In OOPIF enabled modes, this returns a PageState object for the main frame.
PageState GetCurrentPageState();
@@ -188,7 +194,7 @@ class RenderViewTest : public testing::Test, blink::WebLeakDetectorClient {
// We use a naked pointer because we don't want to expose RenderViewImpl in
// the embedder's namespace.
RenderView* view_;
- RendererBlinkPlatformImplNoSandbox blink_platform_impl_;
+ RendererBlinkPlatformImplTestOverride blink_platform_impl_;
scoped_ptr<ContentClient> content_client_;
scoped_ptr<ContentBrowserClient> content_browser_client_;
scoped_ptr<ContentRendererClient> content_renderer_client_;