diff --git a/browser/extensions/formautofill/FormAutofillHandler.jsm b/browser/extensions/formautofill/FormAutofillHandler.jsm index 4d78584799d9..cb36eeb4c3e8 100644 --- a/browser/extensions/formautofill/FormAutofillHandler.jsm +++ b/browser/extensions/formautofill/FormAutofillHandler.jsm @@ -61,36 +61,8 @@ FormAutofillHandler.prototype = { * Set fieldDetails from the form about fields that can be autofilled. */ collectFormFields() { - this.fieldDetails = []; - - for (let element of this.form.elements) { - // Exclude elements to which no autocomplete field has been assigned. - let info = FormAutofillHeuristics.getInfo(element); - if (!info) { - continue; - } - - // Store the association between the field metadata and the element. - if (this.fieldDetails.some(f => f.section == info.section && - f.addressType == info.addressType && - f.contactType == info.contactType && - f.fieldName == info.fieldName)) { - // A field with the same identifier already exists. - log.debug("Not collecting a field matching another with the same info:", info); - continue; - } - - let formatWithElement = { - section: info.section, - addressType: info.addressType, - contactType: info.contactType, - fieldName: info.fieldName, - elementWeakRef: Cu.getWeakReference(element), - }; - - this.fieldDetails.push(formatWithElement); - } - + let fieldDetails = FormAutofillHeuristics.getFormInfo(this.form); + this.fieldDetails = fieldDetails ? fieldDetails : []; log.debug("Collected details on", this.fieldDetails.length, "fields"); }, diff --git a/browser/extensions/formautofill/FormAutofillHeuristics.jsm b/browser/extensions/formautofill/FormAutofillHeuristics.jsm index b188f44119c8..0ce5138a7f03 100644 --- a/browser/extensions/formautofill/FormAutofillHeuristics.jsm +++ b/browser/extensions/formautofill/FormAutofillHeuristics.jsm @@ -12,6 +12,11 @@ this.EXPORTED_SYMBOLS = ["FormAutofillHeuristics"]; const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; +Cu.import("resource://formautofill/FormAutofillUtils.jsm"); + +this.log = null; +FormAutofillUtils.defineLazyLogGetter(this, this.EXPORTED_SYMBOLS[0]); + /** * Returns the autocomplete information of fields according to heuristics. */ @@ -34,6 +39,39 @@ this.FormAutofillHeuristics = { "email", ], + getFormInfo(form) { + let fieldDetails = []; + for (let element of form.elements) { + // Exclude elements to which no autocomplete field has been assigned. + let info = this.getInfo(element); + if (!info) { + continue; + } + + // Store the association between the field metadata and the element. + if (fieldDetails.some(f => f.section == info.section && + f.addressType == info.addressType && + f.contactType == info.contactType && + f.fieldName == info.fieldName)) { + // A field with the same identifier already exists. + log.debug("Not collecting a field matching another with the same info:", info); + continue; + } + + let formatWithElement = { + section: info.section, + addressType: info.addressType, + contactType: info.contactType, + fieldName: info.fieldName, + elementWeakRef: Cu.getWeakReference(element), + }; + + fieldDetails.push(formatWithElement); + } + + return fieldDetails; + }, + getInfo(element) { if (!(element instanceof Ci.nsIDOMHTMLInputElement)) { return null; diff --git a/browser/extensions/formautofill/test/fixtures/autocomplete_basic.html b/browser/extensions/formautofill/test/fixtures/autocomplete_basic.html new file mode 100644 index 000000000000..bb74c9da920c --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/autocomplete_basic.html @@ -0,0 +1,23 @@ + + + + + Form Autofill Demo Page + + +

Form Autofill Demo Page

+
+

+

+

+

+

+

+

+

+

+

+
+ + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/BestBuy/Checkout_Payment.html b/browser/extensions/formautofill/test/fixtures/third_party/BestBuy/Checkout_Payment.html new file mode 100644 index 000000000000..e987ef59cac1 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/BestBuy/Checkout_Payment.html @@ -0,0 +1,283 @@ + + + + Checkout – Best Buy + + +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
    +
  • + +
  • +
+
+
+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+
+
+ +
+
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/BestBuy/Checkout_ShippingAddress.html b/browser/extensions/formautofill/test/fixtures/third_party/BestBuy/Checkout_ShippingAddress.html new file mode 100644 index 000000000000..36760a26108e --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/BestBuy/Checkout_ShippingAddress.html @@ -0,0 +1,326 @@ + + + + Checkout – Best Buy + + +
+ + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
    +
  • + +
  • +
+
+
+
    +
  • + +
  • +
  • + +
  • +
+
+
+
+ +
+
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/BestBuy/SignIn.html b/browser/extensions/formautofill/test/fixtures/third_party/BestBuy/SignIn.html new file mode 100644 index 000000000000..8111d49c3725 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/BestBuy/SignIn.html @@ -0,0 +1,21 @@ + + + + Sign In to BestBuy.com + + +
+
+ + +
+
+ +
+ +
+
+ +
+ + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/CDW/Checkout_BillingPaymentInfo.html b/browser/extensions/formautofill/test/fixtures/third_party/CDW/Checkout_BillingPaymentInfo.html new file mode 100644 index 000000000000..3258417b78cd --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/CDW/Checkout_BillingPaymentInfo.html @@ -0,0 +1,515 @@ + + + + + + Checkout + + + +
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+ + +
+
+
+ Tester + Mo +
+
+ Mozilla +
+
331 E. Evelyn Avenue
+
+ Mountain View, + CA + 94041 +
+
+
+ + +
+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+
The billing address above must match what appears on this credit card's statement.
+
+
+ + +
+
+ + + +
+
+ + + + + +
+
+ + +
+ + +
+
+
+ What is a CVV? +
+ For Visa, MasterCard & Discover, the three digits on the back of your card. +
+ For American Express, the 4 digits on the front of your card. +
+
+
+
+
+
+
+
+
+ +
+ + Verisign Secured + +
+
+ + BBB Accredited Busines + +
+
+
+
+
    +
  • + Edit +
    +
    + Address: +
    +
    +
    + Tester + Mo +
    +
    + Mozilla +
    +
    331 E. Evelyn Avenue
    +
    + Mountain View, + CA + 94041 +
    +
    +
    +
    + Contact Info: +
    +
    +
    + formautofilltester@gmail.com +
    +
    + 650-903-0800 650 +
    +
    +
    +
    +
  • +
  • + Edit +
    +
    Shipping Method
    +
    +
    UPS Ground (2-3 days)
    +
    2-3 business days
    +
    $19.99
    +
    +
    +
  • +
  • + Edit +
    +
    + Billing Address +
    +
    +
    + + + + +
    +
    +
    +
    +
    +
    +
    +
    + +, + + + + +
    +
    +
    Payment Method
    +
    +
    +
    +
  • +
  • +
  • +
+
+ +
+ +
+
+
+
+
+ +
+ +
+ + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/CDW/Checkout_Logon.html b/browser/extensions/formautofill/test/fixtures/third_party/CDW/Checkout_Logon.html new file mode 100644 index 000000000000..6ee46c88731b --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/CDW/Checkout_Logon.html @@ -0,0 +1,118 @@ + + + + + + Logon Checkout + + + +
+
+ + + +
+
+ + +
+

You don't need an account to place an order but you will have the option to create one after completing your purchase.

+
+
+
+

Click or touch the House +

+
+
+ +
+
+
+ + +
+
+ + + +
+ +! The validation code entered is incorrect +
+
+
+ Checkout as Guest + +
+
+
+
+
+ Privacy Policy | Terms and Conditions +
+ + + +
+ +
+
+
+
+
+ User Name + Forgot user name? +
+ +
+
+
+ + +
+ + + + +
+
+
+ Password + Forgot password? +
+ +
+
+
+
+
+ ! You have entered an invalid username and/or password. Please re-enter your information. +
+
+ ! + + +
+ +
+
+ + + + + +
+
+ +
+ + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/CDW/Checkout_ShippingInfo.html b/browser/extensions/formautofill/test/fixtures/third_party/CDW/Checkout_ShippingInfo.html new file mode 100644 index 000000000000..d461a0050b86 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/CDW/Checkout_ShippingInfo.html @@ -0,0 +1,376 @@ + + + + + + Checkout + + + +
+
+ + + +
+
+ + +
+
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
We will only contact you about your order and shipping.
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+ + +
+
+
    +
  • + Edit +
    +
    + Address: +
    +
    +
    + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    + +, + + + + +
    +
    +
    +
    + Contact Info: +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    +
  • +
  • + Edit +
    +
    Shipping Method
    +
    +
    -
    +
    -
    +
    -
    +
    +
    +
  • +
  • + Edit +
    +
    + Billing Address +
    +
    +
    + + + + +
    +
    +
    +
    +
    +
    +
    +
    + +, + + + + +
    +
    +
    Payment Method
    +
    +
    +
    +
  • +
  • +
  • +
+
+
+ +
+
+ +
+ + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/CostCo/Payment.html b/browser/extensions/formautofill/test/fixtures/third_party/CostCo/Payment.html new file mode 100644 index 000000000000..e45176cabc26 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/CostCo/Payment.html @@ -0,0 +1,892 @@ + + + + + + Costco - Payment + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+
+ + +
+
+
+
+ + + +
+
+ + +  ? + +
+
+
+ + +
+
+ + +
+
+
+
+ + + + + + + + + + + + + + + + +
+
+ + +
+
+ + +  ? + +
+         More Info - Costco Cash Card + + Costco Cash Card Number + This image highlights the unique number + cashcard-us.gif + used to identify your Costco Cash card. + Pin Number + This number is used to access your + + Costco Cash card. The image shows + where this number is located. + @ 1998-2016 Costco Wholesale Corporation. All rights reserved. +
+
+
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+
+ +

+* Required fields

+
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ + + +
+ +
+
+ +
+
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+ +

+* Required fields

+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ + + +
+ +
+ +
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ + +
+
+ + +
+
+
+
[rx-DefaultAddrConfirm]
+
+
    +
  • + You are changing your Costco Default Shipping Address.  All future orders from Costco.com, including Pharmacy Prescription Orders, will be sent to this Address. +
  • +
+
+
+
+
+
+
+ +
+
+
+
+
+ + + + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/CostCo/ShippingAddress.html b/browser/extensions/formautofill/test/fixtures/third_party/CostCo/ShippingAddress.html new file mode 100644 index 000000000000..b9b72eb3385c --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/CostCo/ShippingAddress.html @@ -0,0 +1,527 @@ + + + + + + + Shipping + + + + + + +
+ + + + + + +
+
+ + + + + + +
+
+
+ +

+ * Required fields

+
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ + + +
+ +
+
+ +
+
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+ +

+* Required fields

+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ + + +
+ +
+ +
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ + +
+
+ + +
+
+
+
+ [rx-DefaultAddrConfirm] +
+
+
    +
  • You are changing your Costco Default Shipping Address.  All future orders from Costco.com, including Pharmacy Prescription Orders, will be sent to this Address. +
  • +
+
+
+
+
+ + +
+
+ + +
+
+
+
+ +
+
+
+
+
+ + +
+ + +
+
+ + + + + + +
+ + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/CostCo/SignIn.html b/browser/extensions/formautofill/test/fixtures/third_party/CostCo/SignIn.html new file mode 100644 index 000000000000..afcd5fe6f09b --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/CostCo/SignIn.html @@ -0,0 +1,374 @@ + + + + + + Sign In + + + + + + +
+ + +
+ + + + + +
+
+
+
+
+ +
+ +
+ + +
+
+ + + + +
+
+
+
+
  • + +
  • +
    +
    +
    + + +
    +
    +
    + + + + + + + +

    Please provide your email address and password to access your account.† +

    +
    + + +
    +
    +
    + + +

    Passwords are case sensitive.

    +
    +
    +
    + + +
    + +
    + +
    +
    +
    + + + + + + + + + + +

    To reset your password, enter the email address associated with your Costco.com account. Instructions to create a new password will be sent to your address. +

    +
    + + +
    + +
    + +
    +
    +
    + + + + + + + + + + + + + + + + + + +

    Enter your email address and create a password below to register.† +

    +
    +* Required fields +
    +
    + + +
    +
    + + +
    + +
    +

    Password must meet the following:

    +
    +
      +
    • Use between 8 and 20 characters
    • +
    • Include at least one letter
    • +
    • Does not contain blank spaces or the following special characters: < > " \ . +
    • +
    • Passwords match
    • +
    +
    +

    Password Strength : + +

    +
      +
    • Too Short
    • +
    • Weak
    • +
    • Fair
    • +
    • Good
    • +
    • Strong
    • +
    +

    +

    +

    To improve strength, increase password length and use capital letters, numbers, and special characters + (except < > " \ .) +

    +
    +
    +
    +
    + + +
    +
    + + +
    +

    +Non-members may be assessed an additional surcharge. The surcharge does not apply to prescription items. Executive Members need to provide a membership number to receive credit for their 2% rebate. +

    +
    + + +
    + +
    + +
    +
    + +
    +
    + ???LANGUAGE_REGION_MODAL_TITLE??? +
    +
    +
    +

    ???LANGUAGE_REGION_MODAL_CHOOSE_LANGUAGE???

    + +
    +
    +
    +

    ???LANGUAGE_REGION_MODAL_CHOOSE_REGION???

    +
    + + + + + + + +
    +
    + + + + + + +
    +
    +
    + +
    +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/HomeDepot/Checkout_ShippingPayment.html b/browser/extensions/formautofill/test/fixtures/third_party/HomeDepot/Checkout_ShippingPayment.html new file mode 100644 index 000000000000..182535065101 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/HomeDepot/Checkout_ShippingPayment.html @@ -0,0 +1,381 @@ + + + + + + + The Home Depot - Checkout + + + + +
    + + +
    +
    +
    +
    + + + + + + +
    +
    + + + + + + +
    +
    +
    +
    + + + + + + +
    +
    +
    + +
    +
    +
    +Create an account to track your order history and check out faster - all we need is a password.
    +
    +

    Check out faster, access past orders, and organize products into lists.

    +
    +
    +
    +
    + + + + + + + + +
    +
    + + + + + + + + +
    +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    + Passwords are case sensitive and must be at least 8 characters. +
    + Create a strong password by: +
      +
    • Including numbers or symbols
    • +
    • Mixing upper/lowercase
    • +
    +
    +
    + +
    + + +
    +
    +
    +
    +
    +
    + + + + + + +
    +
    +
    +
    +
    +
    + +
    + + +
    + +
    +
    +
    +
    +
    +
    +Add an apartment, suite, building, etc. +
    +
    +
    + + + + +
    +
    + + + +MOUNTAIN VIEW, CA + +
    + + + +
    +
    +
    +
    +
    +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    +
    + +
    +
    + + +
    +
    +
    + Payment +
    +
    +
    +
    + + +
    +
    + + +
    +
    + + + + + + +
    +
    +
    +
    +
    + Expiration + + + +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + + + + +
    +
    +
    + Apply a Gift Card +  |  + Have a PO/Job Code for this order? +
    +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    + + + + +
    +
    +
    + +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    + +
    +
    +Have a promo code? +
    +
    +
    + + + + +
    +
    +
    + + + + + +Apply + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/HomeDepot/SignIn.html b/browser/extensions/formautofill/test/fixtures/third_party/HomeDepot/SignIn.html new file mode 100644 index 000000000000..b741ce5f0c20 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/HomeDepot/SignIn.html @@ -0,0 +1,83 @@ + + + + + The Home Depot - SignIn + + + + + + + +
    + + + + + + + + + + + +
    + + + + +
    +
    +

    You will have the opportunity to create an account and track your order once you complete your checkout. +

    +

    +

    +
    +
    + +
    +
    +
    + + +

    I'm a Returning Customer +

    +
    + Your sign in is incorrect. Please enter your email address or password. Note: One more invalid attempt will lock your account. +
    +
    + We periodically require password updates. Please reset your password or continue as a guest. +
    +
    + + + + +
    +
    + + + + + +
    +
    +
    + +
    +
    + Reset Password +
    +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/Macys/Checkout_Payment.html b/browser/extensions/formautofill/test/fixtures/third_party/Macys/Checkout_Payment.html new file mode 100644 index 000000000000..4ec11c2b857f --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/Macys/Checkout_Payment.html @@ -0,0 +1,478 @@ + + + + + Macy's Checkout + + + + + +
    +
    +
    +
    +
    +
    +
    + + +
    +
    + + + +
    +
    +
    +
    + Note: PayPal can't be used with Gift Cards, Reward Cards and Credit Cards. + Plenti points can be earned but not used with PayPal. +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Secure payment + more info +

    +
    +
    +
    +
    + + +
    Your Shipping, Plenti, and Gift Card information can be found and verified at the top of this page"
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +
    + +
    +
    +
    +
    + + +
    +
    Please enter the 4 digit security code on the front of your credit card
    +
    Please enter the 3 digit security code on the back of your credit card
    +
    +
    + + + + +
    +
    +
    +
    +
    +
    +
    + Note: PayPal can't be used with Gift Cards, Reward Cards and Credit Cards. + Plenti points can be earned but not used with PayPal. +
    +
    +
    +
    + You will login on PayPal's site on the next page and review your order, then you will finish the transaction at macy's.com +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +
    +

    Vance Chen

    +

    1099 Maiden Lane

    +

    102

    +

    Ann Arbor, MI 48105

    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + We'll only contact you if we have questions about this order. +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + + + + + + + + + + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/Macys/Checkout_ShippingAddress.html b/browser/extensions/formautofill/test/fixtures/third_party/Macys/Checkout_ShippingAddress.html new file mode 100644 index 000000000000..7ed68344fa90 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/Macys/Checkout_ShippingAddress.html @@ -0,0 +1,439 @@ + + + + + Macy's Checkout + + + + + + +
    +
    +
    +
    +
    + + +Please enter a first name. +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    +
    + Shipping method +
    +
    +
    +
    +
    + +
    +
    + +
    +
    +
    $10.95 +
    +
    +
    +
    +
    + +
    +
    + +
    +
    +
    $19.95 +
    +
    +
    +
    +
    + +
    +
    + +
    +
    +
    $29.95 +
    +
    +
    +
    +

    +Note: We'll send you an email to schedule your delivery. +

    +

    +Note: Some items in your order may ship separately. Transit time is the time between leaving our fulfillment center & delivery to you. +

    +
    +
    +
    +
    +
    +
    + + Gift Options + +
    +
    +
    +
    + +
    + "Selecting this checkbox will expand additional gift options" +
    + + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    +
    +
    + Write a personal message. We'll print it on a card & send it along with the order. +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    + + + +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/Macys/SignIn.html b/browser/extensions/formautofill/test/fixtures/third_party/Macys/SignIn.html new file mode 100644 index 000000000000..51dff05d0464 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/Macys/SignIn.html @@ -0,0 +1,208 @@ + + + + + Sign In - Macy's Checkout + + + + + + +
    +
    + +
    +
    +Password is case sensitive +
    +
    + Forgot Your Password? +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    + + + + + + + + + + + + + + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/NewEgg/BillingInfo.html b/browser/extensions/formautofill/test/fixtures/third_party/NewEgg/BillingInfo.html new file mode 100644 index 000000000000..c614660e1093 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/NewEgg/BillingInfo.html @@ -0,0 +1,1083 @@ + + + + + Newegg.com - Billing Info + + + + + + + + + +
    +
    + Redeem Newegg gift cards + +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    +
    + + + + Enter A Gift Card + + + +
    + + + +
    +
    + EggPoints +
    +
    + +
    + Payment Methods + + +
    +

    Some payment methods may not be eligible for your order. Please review the full list by clicking here for payment restrictions.

    +
    + + +
    +
    + + +
    +
    + Billing Address + + +
    + + + + + + + + + + + + +
    +
    +
    +
    +
    + +
    + + + + + + + +
    +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    +
    + +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/NewEgg/Login.html b/browser/extensions/formautofill/test/fixtures/third_party/NewEgg/Login.html new file mode 100644 index 000000000000..a5f149b68362 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/NewEgg/Login.html @@ -0,0 +1,156 @@ + + + + + Newegg.com - Login + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    +
    + + CONTINUE AS A GUEST + +
    +
    + + + + + + + +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/NewEgg/ShippingInfo.html b/browser/extensions/formautofill/test/fixtures/third_party/NewEgg/ShippingInfo.html new file mode 100644 index 000000000000..14bd9502afe4 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/NewEgg/ShippingInfo.html @@ -0,0 +1,270 @@ + + + + + Newegg.com - Shipping Info + + + + + + + + + +
    + + + + + + +
    + + + + +
    + + +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/OfficeDepot/Payment.html b/browser/extensions/formautofill/test/fixtures/third_party/OfficeDepot/Payment.html new file mode 100644 index 000000000000..06b9f8e7632b --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/OfficeDepot/Payment.html @@ -0,0 +1,672 @@ + + + + + + + + + + + + + + + + + Office Supplies, Furniture, Technology at Offic Depot + + + +
    + + + + + + + + + + + + + +
    +
    +
    +
    + + +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    + + + +
    +
    + + + + + + + + + + + + + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + +Need Help? +
    +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + +
    +
    +
    +
    +
      +
    • + +
    • +
    • + +
    • +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    + +

    + +

    + + 87 +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    + + + + + + +
    + + + + + + +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/OfficeDepot/ShippingAddress.html b/browser/extensions/formautofill/test/fixtures/third_party/OfficeDepot/ShippingAddress.html new file mode 100644 index 000000000000..849e3be49559 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/OfficeDepot/ShippingAddress.html @@ -0,0 +1,347 @@ + + + + + + + + + + + + + + + + + Office Supplies, Furniture, Technology at Office Depot + + + +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    +
    + + + +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + + + +
    + + + + + + +
    +
    +
    +
    +
    +
    + + + + + + + + + + +
    +
    + + +
    +
    +
    +
    + + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/OfficeDepot/SignIn.html b/browser/extensions/formautofill/test/fixtures/third_party/OfficeDepot/SignIn.html new file mode 100644 index 000000000000..70b55fedddb3 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/OfficeDepot/SignIn.html @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + Office Supplies, Furniture, Technology at Office Depot + + + +
    + + + + + +
    + + + +
    +
    + + + +Forgot login name/password? + +
    +
    + Keep me logged in +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/QVC/PaymentMethod.html b/browser/extensions/formautofill/test/fixtures/third_party/QVC/PaymentMethod.html new file mode 100644 index 000000000000..9d51db7c5d8c --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/QVC/PaymentMethod.html @@ -0,0 +1,527 @@ + + + + + + + + + Payment Method + + +
    + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    +
    +
    +
      +
    • + + +
    • +
    • + + +
    • +
    + + +
    +
    +
    + + + + + + + + + + + + + + + + +
    + + + (formerly Bill Me Later®) +
    +
    +
    + + +
    +
    + + +
    +
    + XXX-XX- +
    +
    + + + + + + +
    +
    +
    + +
    +
    +
    +
    + + +
    +
    + +      +
    +
    +
    + + + + + +
    + + +
    +
    +
    +
    +   +
    +
    +
    + + + + + +
    +
    +
    +
    +
    +
    +
    + + +
    +
    + + + + + + + Enter Another Card + +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    + + + Continue Checkout + + + Continue Checkout + + + + + Edit Shopping cart + +
    +
    +
    +
    + + * + + + + *You're signing up to receive QVC promotional email. +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/QVC/SignIn.html b/browser/extensions/formautofill/test/fixtures/third_party/QVC/SignIn.html new file mode 100644 index 000000000000..a056ccfc5cc5 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/QVC/SignIn.html @@ -0,0 +1,80 @@ + + + + + + + + QVC.com Sign In + + +
    +
    + + + + + + +
    +
    +
    + +
    + + + + + + + + +
    +
    + + +
    + + +
    +
    +
    +
    + + + +
    +
    +
    +
    + + Create Password + + + + Continue + + +
    +
    + + Sign In + + +
    +
    +
    + +
    +
    +
    + +
    + + Continue + + +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/QVC/YourInformation.html b/browser/extensions/formautofill/test/fixtures/third_party/QVC/YourInformation.html new file mode 100644 index 000000000000..7af160e354cc --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/QVC/YourInformation.html @@ -0,0 +1,522 @@ + + + + + + + + + Payment Method + + +
    + + + + + + + + + + + + + + + + + + + +
    +
    +
      +
    • + + +
    • +
    • + + +
    • +
    + + +
    +
    +
    + + + + + + + + + + + + + + + + +
    + + +
    +
    +
    + + +
    +
    + + +
    +
    + XXX-XX- +
    +
    + + + + + + +
    +
    +
    + +
    +
    +
    +
    + + +
    +
    + +      +
    +
    +
    + + + + + +
    + + +
    +
    +
    +
    +   +
    +
    +
    + + + Add My QCard + + + +
    +
    +
    +
    +
    +
    +
    + + +
    +
    + + + + + + + Enter Another Card + +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    + + + Continue Checkout + + + Continue Checkout + + + + + Edit Shopping cart + +
    +
    +
    +
    + + * + + + + *You're signing up to receive QVC promotional email. +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/README b/browser/extensions/formautofill/test/fixtures/third_party/README new file mode 100644 index 000000000000..ca4750ec08cf --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/README @@ -0,0 +1,4 @@ +This directory contains pages downloaded from the web for the purpose of testing +Form Autofill against pages from the real world. These files are not made +available under an open source license. + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/Sears/PaymentOptions.html b/browser/extensions/formautofill/test/fixtures/third_party/Sears/PaymentOptions.html new file mode 100644 index 000000000000..5f6ecd24d9d7 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/Sears/PaymentOptions.html @@ -0,0 +1,566 @@ + + + + + + + + + + + Payment Options | Sears PartsDirect + + + + +
    +
    + + + + + + +
    +
    +
    + + + + + + + +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    + +
    +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    +
    + + + + + + + +
    + + +
    +
    + + +
    + +
    + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    +
    + + +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/Sears/ShippingAddress.html b/browser/extensions/formautofill/test/fixtures/third_party/Sears/ShippingAddress.html new file mode 100644 index 000000000000..a9d1f5cd0f3f --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/Sears/ShippingAddress.html @@ -0,0 +1,447 @@ + + + + + + + + + + + Shipping address | Sears PartsDirect + + + + +
    +
    + + + + + + +
    +
    +
    + +
    + +
    +
    + +
    +
    + +
    +
    + +
    + +
    +
    +
    +

    +

    +
    + + + +
    +
    + +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    +
    +
    + + +
    24 character limit
    +
    +
    + + +
    +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    + +
    +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    + + + +
    +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    + +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    +
    + + + + + + +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    + + + +
    +
    + +
    +
    +
    + + +
    +
    +
    + + +
    +
    +
    + + + + + +
    + + +
    +
    + + +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/Staples/Basic.html b/browser/extensions/formautofill/test/fixtures/third_party/Staples/Basic.html new file mode 100644 index 000000000000..cf9e892cb2b2 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/Staples/Basic.html @@ -0,0 +1,117 @@ + + + + + It's easy to find the Office Supplies, Copy Paper, + Furniture, Ink, Toner, Cleaning Products, Electronics and the + Technology you need | Staples® + + + + + + + + + + +
    + +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/Staples/Basic_ac_on.html b/browser/extensions/formautofill/test/fixtures/third_party/Staples/Basic_ac_on.html new file mode 100644 index 000000000000..d3ba1116aabf --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/Staples/Basic_ac_on.html @@ -0,0 +1,117 @@ + + + + + It's easy to find the Office Supplies, Copy Paper, + Furniture, Ink, Toner, Cleaning Products, Electronics and the + Technology you need | Staples® + + + + + + + + + + +
    + +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/Staples/PaymentBilling.html b/browser/extensions/formautofill/test/fixtures/third_party/Staples/PaymentBilling.html new file mode 100644 index 000000000000..37dadeb514a9 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/Staples/PaymentBilling.html @@ -0,0 +1,99 @@ + + + + + It's easy to find the Office Supplies, Copy Paper, + Furniture, Ink, Toner, Cleaning Products, Electronics and the + Technology you need | Staples® + + + + + + + + + + +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    +
    +
    +
    + + +
    +
    +
    +
    + +
    +
    +

    Purchase Order # (optional) Add +

    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +

    +By placing your order, you agree to + Staples + +Terms & + Conditions. + +

    +
    +
    +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/Staples/PaymentBilling_ac_on.html b/browser/extensions/formautofill/test/fixtures/third_party/Staples/PaymentBilling_ac_on.html new file mode 100644 index 000000000000..98c9fb85555b --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/Staples/PaymentBilling_ac_on.html @@ -0,0 +1,98 @@ + + + + + It's easy to find the Office Supplies, Copy Paper, + Furniture, Ink, Toner, Cleaning Products, Electronics and the + Technology you need | Staples® + + + + + + + + + + +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    +
    +
    +
    + + +
    +
    +
    +
    + +
    +
    +

    Purchase Order # (optional) Add +

    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +

    +By placing your order, you agree to + Staples + +Terms & + Conditions. + +

    +
    +
    +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/Walmart/Checkout.html b/browser/extensions/formautofill/test/fixtures/third_party/Walmart/Checkout.html new file mode 100644 index 000000000000..0d59eec17280 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/Walmart/Checkout.html @@ -0,0 +1,243 @@ + + + + + + + + + + + + +
    +

    Enter new zip code:

    + +
    +

    + +

    + +
    +
    +
    + +
    +
    + +
    +
    +
    +
    + +
    + +
    + +
    +
    +
    +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    +
    *required field
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    + + +
    +
    +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    +
    +
    +
    + +By clicking Create Account, you acknowledge you + have read and agreed to our +Terms of + Use +and +Privacy + Policy +. + +
    + +
    +
    + + +
    +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/Walmart/Payment.html b/browser/extensions/formautofill/test/fixtures/third_party/Walmart/Payment.html new file mode 100644 index 000000000000..26936843291a --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/Walmart/Payment.html @@ -0,0 +1,235 @@ + + + + + + + + + Checkout + + + + + + + + + + + +
    + +
    + +
    + +
    +
    +
    +
    +
    +
    * required field
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    +
    +
    + +
    + + + +
    +  /  +
    + + + +
    +
    +
    +
    + + +
    +
    + +
    + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +

    +22F., No.55, Haiiu 1st Rd., Bafu Dist., +
    + +San Bruno +, + + +CA + +94066 +

    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + + diff --git a/browser/extensions/formautofill/test/fixtures/third_party/Walmart/Shipping.html b/browser/extensions/formautofill/test/fixtures/third_party/Walmart/Shipping.html new file mode 100644 index 000000000000..908453b7f1e0 --- /dev/null +++ b/browser/extensions/formautofill/test/fixtures/third_party/Walmart/Shipping.html @@ -0,0 +1,234 @@ + + + + + + + + + Checkout + + + + + + + + + + + +
    +

    Enter new zip code:

    + +
    +

    + +

    + +
    +
    +
    + +
    +
    + +
    +
    +
    +
    + +
    + +
    + +
    +
    +
    +
    +
    +
    +
    *required field
    + +
    + +
    + +
    + +
    + +
    + +
    +
    +
    + +
    + +
    + +
    + +
    + +
    + +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    + + diff --git a/browser/extensions/formautofill/test/unit/head.js b/browser/extensions/formautofill/test/unit/head.js index a49757a340ba..0bf3608ba4e4 100644 --- a/browser/extensions/formautofill/test/unit/head.js +++ b/browser/extensions/formautofill/test/unit/head.js @@ -2,7 +2,7 @@ * Provides infrastructure for automated formautofill components tests. */ -/* exported loadFormAutofillContent, getTempFile, sinon */ +/* exported getTempFile, loadFormAutofillContent, runHeuristicsTest, sinon */ "use strict"; @@ -79,6 +79,45 @@ function getTempFile(leafName) { return file; } +function runHeuristicsTest(patterns, fixturePathPrefix) { + Cu.import("resource://gre/modules/FormLikeFactory.jsm"); + Cu.import("resource://formautofill/FormAutofillHeuristics.jsm"); + + // TODO: "select" and "textarea" will be included eventually. + const QUERY_STRING = ["input"]; + patterns.forEach(testPattern => { + add_task(function* () { + do_print("Starting test fixture: " + testPattern.fixturePath); + let file = do_get_file(fixturePathPrefix + testPattern.fixturePath); + let doc = MockDocument.createTestDocumentFromFile("http://localhost:8080/test/", file); + + let forms = []; + + for (let query of QUERY_STRING) { + for (let field of doc.querySelectorAll(query)) { + let formLike = FormLikeFactory.createFromField(field); + if (!forms.some(form => form.rootElement === formLike.rootElement)) { + forms.push(formLike); + } + } + } + + Assert.equal(forms.length, testPattern.expectedResult.length, "Expected form count."); + + forms.forEach((form, formIndex) => { + let formInfo = FormAutofillHeuristics.getFormInfo(form); + // TODO: This line should be uncommented to make sure every field are verified. + // Assert.equal(formInfo.length, testPattern.expectedResult[formIndex].length, "Expected field count."); + formInfo.forEach((field, fieldIndex) => { + let expectedField = testPattern.expectedResult[formIndex][fieldIndex]; + expectedField.elementWeakRef = field.elementWeakRef; + Assert.deepEqual(field, expectedField); + }); + }); + }); + }); +} + add_task(function* head_initialize() { Services.prefs.setBoolPref("browser.formautofill.experimental", true); Services.prefs.setBoolPref("dom.forms.autocomplete.experimental", true); diff --git a/browser/extensions/formautofill/test/unit/heuristics/test_basic.js b/browser/extensions/formautofill/test/unit/heuristics/test_basic.js new file mode 100644 index 000000000000..5f3c7759c85e --- /dev/null +++ b/browser/extensions/formautofill/test/unit/heuristics/test_basic.js @@ -0,0 +1,22 @@ +/* global runHeuristicsTest */ + +"use strict"; + +runHeuristicsTest([ + { + fixturePath: "autocomplete_basic.html", + expectedResult: [ + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "organization"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "country"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + ], + }, +], "../../fixtures/"); + diff --git a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_BestBuy.js b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_BestBuy.js new file mode 100644 index 000000000000..60df0f661a29 --- /dev/null +++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_BestBuy.js @@ -0,0 +1,56 @@ +/* global runHeuristicsTest */ + +"use strict"; + +runHeuristicsTest([ + { + fixturePath: "Checkout_ShippingAddress.html", + expectedResult: [ + [], // Search form + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, // city +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // TODO:select,state + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + ], + [ // Sign up + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [ // unknown + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, + ], + ], + }, { + fixturePath: "Checkout_Payment.html", + expectedResult: [ + [], // Search form + [ // Sign up + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, // city +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // TODO:select,state + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + ], + [ + // unknown + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, + ], + ], + }, { + fixturePath: "SignIn.html", + expectedResult: [ + [ // Sign in + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + ], + }, +], "../../../fixtures/third_party/BestBuy/"); + diff --git a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_CDW.js b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_CDW.js new file mode 100644 index 000000000000..6c7a5fe0d2b8 --- /dev/null +++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_CDW.js @@ -0,0 +1,55 @@ +/* global runHeuristicsTest */ + +"use strict"; + +runHeuristicsTest([ + { + fixturePath: "Checkout_ShippingInfo.html", + expectedResult: [ + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "organization"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, // city +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // TODO: select,state + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, + ], + [], + ], + }, { + fixturePath: "Checkout_BillingPaymentInfo.html", + expectedResult: [ + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "organization"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, // city +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // TODO: select,state + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + ], + [ + /* TODO: Credit Card + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-type"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, +*/ + ], + ], + }, { + fixturePath: "Checkout_Logon.html", + expectedResult: [ + [], + [], + [], + ], + }, +], "../../../fixtures/third_party/CDW/"); + diff --git a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_CostCo.js b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_CostCo.js new file mode 100644 index 000000000000..f5e77d42fe77 --- /dev/null +++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_CostCo.js @@ -0,0 +1,124 @@ +/* global runHeuristicsTest */ + +"use strict"; + +runHeuristicsTest([ + { + fixturePath: "ShippingAddress.html", + expectedResult: [ + [], + [], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "additional-name"}, // middle-name initial + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "organization"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "country"}, // TODO: select,country + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"}, // TODO: fix the regexp + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, // city +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // TODO: select,state + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "additional-name"}, // middle-name initial + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "organization"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "country"}, // TODO: select,country + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"}, // TODO: fix the regexp + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, // city +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // TODO: select,state + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [], + ], + }, { + fixturePath: "Payment.html", + expectedResult: [ + [ +/* TODO: credit card + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-type"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, // ac-off + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-name"}, // ac-off +*/ + ], + [], + [], + [], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "additional-name"}, // middle-name initial + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "organization"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "country"}, // TODO: select, country + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"}, // TODO: fix the regexp + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, // city +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // TODO: select, state + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "additional-name"}, // middle-name initial + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "organization"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "country"}, // TODO: select, country + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"}, // TODO: fix the regexp + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // TODO: select, state + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [], + ], + }, { + fixturePath: "SignIn.html", + expectedResult: [ + [], + [], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [], + [ // Forgot password + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "password"}, + ], + [ // Sign up + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [], + ], + }, +], "../../../fixtures/third_party/CostCo/"); + diff --git a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_HomeDepot.js b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_HomeDepot.js new file mode 100644 index 000000000000..77993b6c66a9 --- /dev/null +++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_HomeDepot.js @@ -0,0 +1,34 @@ +/* global runHeuristicsTest */ + +"use strict"; + +runHeuristicsTest([ + { + fixturePath: "Checkout_ShippingPayment.html", + expectedResult: [ + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, + ], + ], + }, { + fixturePath: "SignIn.html", + expectedResult: [ + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + ], + }, +], "../../../fixtures/third_party/HomeDepot/"); + diff --git a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Macys.js b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Macys.js new file mode 100644 index 000000000000..6a957ae5e6ad --- /dev/null +++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Macys.js @@ -0,0 +1,67 @@ +/* global runHeuristicsTest */ + +"use strict"; + +runHeuristicsTest([ + { + fixturePath: "Checkout_ShippingAddress.html", + expectedResult: [ + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // select + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, + ], + [ +/* +*/ + ], + ], + }, { + fixturePath: "Checkout_Payment.html", + expectedResult: [ + [ + /* + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-type"}, // ac-off + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"}, // ac-off + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"}, // ac-off + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, // ac-off + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, // ac-off +*/ + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // select + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [], + ], + }, { + fixturePath: "SignIn.html", + expectedResult: [ + [ // Sign in + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "password"}, + ], + [ // Forgot password + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [], + [], + [], + ], + }, +], "../../../fixtures/third_party/Macys/"); + diff --git a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_NewEgg.js b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_NewEgg.js new file mode 100644 index 000000000000..d5479f364d52 --- /dev/null +++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_NewEgg.js @@ -0,0 +1,66 @@ +/* global runHeuristicsTest */ + +"use strict"; + +runHeuristicsTest([ + { + fixturePath: "ShippingInfo.html", + expectedResult: [ + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "country"}, // TODO: select, country + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // TODO: select, state + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [], + ], + }, { + fixturePath: "BillingInfo.html", + expectedResult: [ + [ +/* TODO: Should match the following fields. + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, +*/ +// {"section": "", "addressType": "", "contactType": "", "fieldName": "country"}, // TODO: select, country + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // TODO: select, country + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-name"}, // TODO +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // TODO +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"}, // TODO +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"}, // TODO + ], + [], + [], + [], + ], + }, { + fixturePath: "Login.html", + expectedResult: [ + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + ], + }, +], "../../../fixtures/third_party/NewEgg/"); + diff --git a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_OfficeDepot.js b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_OfficeDepot.js new file mode 100644 index 000000000000..c553615c765f --- /dev/null +++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_OfficeDepot.js @@ -0,0 +1,64 @@ +/* global runHeuristicsTest */ + +"use strict"; + +runHeuristicsTest([ + { + fixturePath: "ShippingAddress.html", + expectedResult: [ + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "organization"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // TODO: select, state + + // TODO: telphone relative fields should be fixed: + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel-area-code"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-prefix"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-suffix"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"}, + + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [], + ], + }, { + fixturePath: "Payment.html", + expectedResult: [ + [ +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "organization"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // TODO: select, state + + // TODO: telphone relative fields should be fixed: + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel-area-code"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-prefix"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-suffix"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"}, + + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + ], + }, { + fixturePath: "SignIn.html", + expectedResult: [ + [ // ac-off +// {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + ], + }, +], "../../../fixtures/third_party/OfficeDepot/"); + diff --git a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_QVC.js b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_QVC.js new file mode 100644 index 000000000000..d2b088ca9d49 --- /dev/null +++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_QVC.js @@ -0,0 +1,54 @@ +/* global runHeuristicsTest */ + +"use strict"; + +runHeuristicsTest([ + { + fixturePath: "YourInformation.html", + expectedResult: [ + [ +// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, // ac-off + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-year"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-type"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, + ], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + ], + }, { + fixturePath: "PaymentMethod.html", + expectedResult: [ + [ +// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, // ac-off + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-month"}, // select +// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-day"}, // select +// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-year"}, // select +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-type"}, // select +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp"}, // select +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, + ], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + ], + }, { + fixturePath: "SignIn.html", + expectedResult: [ + [ + // Unknown + ], + [ // Sign in + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [], + ], + }, +], "../../../fixtures/third_party/QVC/"); + diff --git a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Sears.js b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Sears.js new file mode 100644 index 000000000000..60fe39e55ad2 --- /dev/null +++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Sears.js @@ -0,0 +1,87 @@ +/* global runHeuristicsTest */ + +"use strict"; + +runHeuristicsTest([ + { + fixturePath: "ShippingAddress.html", + expectedResult: [ + [], + [], // search form, ac-off + [ // ac-off +// {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [ // check-out, ac-off +/* + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, +*/ + ], + [ // ac-off +/* + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "new-password"}, +*/ + ], + [ // ac-off +// {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + [ // ac-off +// {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + ], + }, { + fixturePath: "PaymentOptions.html", + expectedResult: [ + [], + [], // search + [ // credit card +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-name"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"}, + ], + [ // Another billing address + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // TODO: select, state + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"}, + ], + [ // check out + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // TODO: Wrong. This is for Driver's license. +// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-month"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-day"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-year"}, + ], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + ], + ], + }, +], "../../../fixtures/third_party/Sears/"); + diff --git a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Staples.js b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Staples.js new file mode 100644 index 000000000000..240aa0fbbea3 --- /dev/null +++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Staples.js @@ -0,0 +1,48 @@ +/* global runHeuristicsTest */ + +"use strict"; + +runHeuristicsTest([ + { + fixturePath: "Basic.html", + expectedResult: [ + [ // ac-off +// {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "organization"}, + ], + ], + }, { + fixturePath: "Basic_ac_on.html", + expectedResult: [ + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "organization"}, + ], + ], + }, { + fixturePath: "PaymentBilling.html", + expectedResult: [ + [], + ], + }, { + fixturePath: "PaymentBilling_ac_on.html", + expectedResult: [ + [ +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, + ], + ], + }, +], "../../../fixtures/third_party/Staples/"); + diff --git a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Walmart.js b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Walmart.js new file mode 100644 index 000000000000..4d8d67953a63 --- /dev/null +++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Walmart.js @@ -0,0 +1,62 @@ +/* global runHeuristicsTest */ + +"use strict"; + +runHeuristicsTest([ + { + fixturePath: "Checkout.html", + expectedResult: [ + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + ], + [ + ], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "password"}, // ac-off + ], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "email"}, // ac-off +// {"section": "", "addressType": "", "contactType": "", "fieldName": "password"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "password"}, // ac-off + ], + ], + }, { + fixturePath: "Payment.html", + expectedResult: [ + [ + ], + [ + {"section": "section-payment", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "section-payment", "addressType": "", "contactType": "", "fieldName": "family-name"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, + {"section": "section-payment", "addressType": "", "contactType": "", "fieldName": "tel"}, + ], + ], + }, { + fixturePath: "Shipping.html", + expectedResult: [ + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + ], + [ + ], + [ + {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"}, +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"}, // TODO: fix the regexp + {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, // city +// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // TODO: select, state + {"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"}, + ], + ], + }, +], "../../../fixtures/third_party/Walmart/"); + diff --git a/browser/extensions/formautofill/test/unit/xpcshell.ini b/browser/extensions/formautofill/test/unit/xpcshell.ini index 78c472186503..724e799c2e71 100644 --- a/browser/extensions/formautofill/test/unit/xpcshell.ini +++ b/browser/extensions/formautofill/test/unit/xpcshell.ini @@ -2,7 +2,20 @@ firefox-appdir = browser head = head.js support-files = + ../fixtures/** +[heuristics/test_basic.js] +[heuristics/third_party/test_BestBuy.js] +[heuristics/third_party/test_CDW.js] +[heuristics/third_party/test_CostCo.js] +[heuristics/third_party/test_HomeDepot.js] +[heuristics/third_party/test_Macys.js] +[heuristics/third_party/test_NewEgg.js] +[heuristics/third_party/test_OfficeDepot.js] +[heuristics/third_party/test_QVC.js] +[heuristics/third_party/test_Sears.js] +[heuristics/third_party/test_Staples.js] +[heuristics/third_party/test_Walmart.js] [test_autofillFormFields.js] [test_collectFormFields.js] [test_enabledStatus.js] diff --git a/devtools/client/locales/en-US/netmonitor.properties b/devtools/client/locales/en-US/netmonitor.properties index 75f0e0b62e57..e6f6b57dc43a 100644 --- a/devtools/client/locales/en-US/netmonitor.properties +++ b/devtools/client/locales/en-US/netmonitor.properties @@ -219,6 +219,12 @@ networkMenu.sizeServiceWorker=service worker # in the network menu specifying the time for a request to finish (in milliseconds). networkMenu.totalMS=→ %S ms +# This string is used to concatenate tooltips (netmonitor.waterfall.tooltip.*) +# in the requests waterfall for total time (in milliseconds). \\u0020 represents +# a whitespace. You can replace this with a different character, e.g. an hyphen +# or a period, if a comma doesn't work for your language. +netmonitor.waterfall.tooltip.separator=,\u0020 + # LOCALIZATION NOTE (netmonitor.waterfall.tooltip.total): This is part of the tooltip # displayed in the requests waterfall for total time (in milliseconds). netmonitor.waterfall.tooltip.total=Total %S ms diff --git a/devtools/client/netmonitor/src/components/request-list-column-waterfall.js b/devtools/client/netmonitor/src/components/request-list-column-waterfall.js index a6277655c146..1fdf07b7eeb0 100644 --- a/devtools/client/netmonitor/src/components/request-list-column-waterfall.js +++ b/devtools/client/netmonitor/src/components/request-list-column-waterfall.js @@ -96,7 +96,10 @@ function timingBoxes(item) { tooltip.push(L10N.getFormatStr("netmonitor.waterfall.tooltip.total", totalTime)); } - return { boxes, tooltip: tooltip.join(", ") }; + return { + boxes, + tooltip: tooltip.join(L10N.getStr("netmonitor.waterfall.tooltip.separator")) + }; } module.exports = RequestListColumnWaterfall; diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index a35f546208d6..69d675ff80ac 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -3094,12 +3094,7 @@ nsContentUtils::CheckQName(const nsAString& aQualifiedName, return NS_OK; } - // MOZ_EXPAT_EMPTY_QNAME || MOZ_EXPAT_INVALID_CHARACTER - if (result == (1 << 0) || result == (1 << 1)) { - return NS_ERROR_DOM_INVALID_CHARACTER_ERR; - } - - return NS_ERROR_DOM_NAMESPACE_ERR; + return NS_ERROR_DOM_INVALID_CHARACTER_ERR; } //static diff --git a/dom/tests/mochitest/dom-level2-core/test_createAttributeNS01.html b/dom/tests/mochitest/dom-level2-core/test_createAttributeNS01.html index aea5a3a6e0cf..727ee15f8caf 100644 --- a/dom/tests/mochitest/dom-level2-core/test_createAttributeNS01.html +++ b/dom/tests/mochitest/dom-level2-core/test_createAttributeNS01.html @@ -108,9 +108,9 @@ function createAttributeNS01() { newAttr = doc.createAttributeNS(namespaceURI,malformedName); } catch(ex) { - success = (typeof(ex.code) != 'undefined' && ex.code == 14); + success = ex.code === DOMException.INVALID_CHARACTER_ERR; } - assertTrue("throw_NAMESPACE_ERR",success); + assertTrue("throw INVALID_CHARACTER_ERR",success); } } diff --git a/dom/tests/mochitest/dom-level2-core/test_createDocument01.html b/dom/tests/mochitest/dom-level2-core/test_createDocument01.html index ffc032082893..173c2bdb824b 100644 --- a/dom/tests/mochitest/dom-level2-core/test_createDocument01.html +++ b/dom/tests/mochitest/dom-level2-core/test_createDocument01.html @@ -114,9 +114,9 @@ function createDocument01() { aNewDoc = domImpl.createDocument(namespaceURI,malformedName,docType); } catch(ex) { - success = (typeof(ex.code) != 'undefined' && ex.code == 14); + success = ex.code === DOMException.INVALID_CHARACTER_ERR; } - assertTrue("throw_NAMESPACE_ERR",success); + assertTrue("throw INVALID_CHARACTER_ERR",success); } } diff --git a/dom/tests/mochitest/dom-level2-core/test_createDocumentType01.html b/dom/tests/mochitest/dom-level2-core/test_createDocumentType01.html index d52ce64e1c44..d6d460d00969 100644 --- a/dom/tests/mochitest/dom-level2-core/test_createDocumentType01.html +++ b/dom/tests/mochitest/dom-level2-core/test_createDocumentType01.html @@ -112,9 +112,9 @@ function createDocumentType01() { newType = domImpl.createDocumentType(malformedName,publicId,systemId); } catch(ex) { - success = (typeof(ex.code) != 'undefined' && ex.code == 14); + success = ex.code === DOMException.INVALID_CHARACTER_ERR; } - assertTrue("throw_NAMESPACE_ERR",success); + assertTrue("throw INVALID_CHARACTER_ERR", success); } } diff --git a/dom/tests/mochitest/dom-level2-core/test_createElementNS01.html b/dom/tests/mochitest/dom-level2-core/test_createElementNS01.html index e15464d3b42a..e592d096fbd6 100644 --- a/dom/tests/mochitest/dom-level2-core/test_createElementNS01.html +++ b/dom/tests/mochitest/dom-level2-core/test_createElementNS01.html @@ -108,9 +108,9 @@ function createElementNS01() { newElement = doc.createElementNS(namespaceURI,malformedName); } catch(ex) { - success = (typeof(ex.code) != 'undefined' && ex.code == 14); + success = ex.code === DOMException.INVALID_CHARACTER_ERR; } - assertTrue("throw_NAMESPACE_ERR",success); + assertTrue("throw INVALID_CHARACTER_ERR", success); } } diff --git a/dom/tests/mochitest/dom-level2-core/test_documentcreateattributeNS04.html b/dom/tests/mochitest/dom-level2-core/test_documentcreateattributeNS04.html index 89e34b874d30..1485f75a07bf 100644 --- a/dom/tests/mochitest/dom-level2-core/test_documentcreateattributeNS04.html +++ b/dom/tests/mochitest/dom-level2-core/test_documentcreateattributeNS04.html @@ -113,7 +113,7 @@ function documentcreateattributeNS04() { attribute = doc.createAttributeNS(namespaceURI,qualifiedName); } catch(ex) { - success = (typeof(ex.code) != 'undefined' && ex.code == 14); + success = ex.code === DOMException.INVALID_CHARACTER_ERR; } assertTrue("documentcreateattributeNS04",success); } diff --git a/dom/tests/mochitest/dom-level2-core/test_domimplementationcreatedocument07.html b/dom/tests/mochitest/dom-level2-core/test_domimplementationcreatedocument07.html index b87b2150cb87..056fa2d256ec 100644 --- a/dom/tests/mochitest/dom-level2-core/test_domimplementationcreatedocument07.html +++ b/dom/tests/mochitest/dom-level2-core/test_domimplementationcreatedocument07.html @@ -106,7 +106,7 @@ function domimplementationcreatedocument07() { newDoc = domImpl.createDocument(namespaceURI,":",docType); } catch(ex) { - success = (typeof(ex.code) != 'undefined' && ex.code == 14); + success = ex.code === DOMException.INVALID_CHARACTER_ERR; } assertTrue("domimplementationcreatedocument07",success); } diff --git a/dom/tests/mochitest/dom-level2-core/test_setAttributeNS02.html b/dom/tests/mochitest/dom-level2-core/test_setAttributeNS02.html index 6f58738f6cf6..de73321e66b9 100644 --- a/dom/tests/mochitest/dom-level2-core/test_setAttributeNS02.html +++ b/dom/tests/mochitest/dom-level2-core/test_setAttributeNS02.html @@ -109,9 +109,9 @@ function setAttributeNS02() { testAddr.setAttributeNS(namespaceURI,qualifiedName,"newValue"); } catch(ex) { - success = (typeof(ex.code) != 'undefined' && ex.code == 14); + success = ex.code === DOMException.INVALID_CHARACTER_ERR; } - assertTrue("throw_NAMESPACE_ERR",success); + assertTrue("throw INVALID_CHARACTER_ERR",success); } } diff --git a/layout/reftests/css-break/reftest.list b/layout/reftests/css-break/reftest.list index c85d4238cbd0..28f60935b9c0 100644 --- a/layout/reftests/css-break/reftest.list +++ b/layout/reftests/css-break/reftest.list @@ -6,7 +6,7 @@ fuzzy(16,460) fuzzy-if(Android,10,3673) fuzzy-if(skiaContent,32,254) == box-deco random-if(!gtkWidget) HTTP(..) == box-decoration-break-border-image.html box-decoration-break-border-image-ref.html == box-decoration-break-block-border-padding.html box-decoration-break-block-border-padding-ref.html == box-decoration-break-block-margin.html box-decoration-break-block-margin-ref.html -fuzzy-if(!Android,1,62) fuzzy-if(Android,8,6627) fails-if(stylo) == box-decoration-break-first-letter.html box-decoration-break-first-letter-ref.html #Bug 1313773 +fuzzy-if(!Android,1,62) fuzzy-if(Android,8,6627) == box-decoration-break-first-letter.html box-decoration-break-first-letter-ref.html #Bug 1313773 == box-decoration-break-with-bidi.html box-decoration-break-with-bidi-ref.html == box-decoration-break-bug-1235152.html box-decoration-break-bug-1235152-ref.html == box-decoration-break-bug-1249913.html box-decoration-break-bug-1249913-ref.html diff --git a/layout/style/test/stylo-failures.md b/layout/style/test/stylo-failures.md index 67f2f2bfca9e..01cf0e8f81a6 100644 --- a/layout/style/test/stylo-failures.md +++ b/layout/style/test/stylo-failures.md @@ -128,7 +128,7 @@ to mochitest command. * test_initial_storage.html `-moz-force-broken-image-icon` [4] * test_value_storage.html `-moz-force-broken-image-icon` [4] * -moz-transform: need different parsing rules servo/servo#16003 - * test_value_storage.html `-moz-transform`: need different parsing rules bug 1357906 [72] + * test_value_storage.html `-moz-transform`: need different parsing rules bug 1357906 [70] * test_variables.html `var(--var6)`: -x-system-font [1] * Unimplemented CSS properties: * place-{content,items,self} shorthands servo/servo#16391 diff --git a/servo/components/gfx/display_list/mod.rs b/servo/components/gfx/display_list/mod.rs index 205b4071589c..77a64553c29f 100644 --- a/servo/components/gfx/display_list/mod.rs +++ b/servo/components/gfx/display_list/mod.rs @@ -528,6 +528,7 @@ pub enum DisplayItem { WebGL(Box), Border(Box), Gradient(Box), + RadialGradient(Box), Line(Box), BoxShadow(Box), Iframe(Box), @@ -889,6 +890,9 @@ pub struct Gradient { /// A list of color stops. pub stops: Vec, + + /// True if gradient repeats infinitly. + pub repeating: bool, } #[derive(Clone, Deserialize, HeapSizeOf, Serialize)] @@ -900,6 +904,31 @@ pub struct GradientDisplayItem { pub gradient: Gradient, } +/// Paints a radial gradient. +#[derive(Clone, Deserialize, HeapSizeOf, Serialize)] +pub struct RadialGradient { + /// The center point of the gradient. + pub center: Point2D, + + /// The radius of the gradient with an x and an y component. + pub radius: Size2D, + + /// A list of color stops. + pub stops: Vec, + + /// True if gradient repeats infinitly. + pub repeating: bool, +} + +#[derive(Clone, Deserialize, HeapSizeOf, Serialize)] +pub struct RadialGradientDisplayItem { + /// Fields common to all display item. + pub base: BaseDisplayItem, + + /// Contains all gradient data. + pub gradient: RadialGradient, +} + /// A normal border, supporting CSS border styles. #[derive(Clone, HeapSizeOf, Deserialize, Serialize)] pub struct NormalBorder { @@ -1124,6 +1153,7 @@ impl DisplayItem { DisplayItem::WebGL(ref webgl_item) => &webgl_item.base, DisplayItem::Border(ref border) => &border.base, DisplayItem::Gradient(ref gradient) => &gradient.base, + DisplayItem::RadialGradient(ref gradient) => &gradient.base, DisplayItem::Line(ref line) => &line.base, DisplayItem::BoxShadow(ref box_shadow) => &box_shadow.base, DisplayItem::Iframe(ref iframe) => &iframe.base, @@ -1241,6 +1271,7 @@ impl fmt::Debug for DisplayItem { DisplayItem::WebGL(_) => "WebGL".to_owned(), DisplayItem::Border(_) => "Border".to_owned(), DisplayItem::Gradient(_) => "Gradient".to_owned(), + DisplayItem::RadialGradient(_) => "RadialGradient".to_owned(), DisplayItem::Line(_) => "Line".to_owned(), DisplayItem::BoxShadow(_) => "BoxShadow".to_owned(), DisplayItem::Iframe(_) => "Iframe".to_owned(), diff --git a/servo/components/layout/display_list_builder.rs b/servo/components/layout/display_list_builder.rs index 2e065572615d..a2453067e1f5 100644 --- a/servo/components/layout/display_list_builder.rs +++ b/servo/components/layout/display_list_builder.rs @@ -25,7 +25,7 @@ use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDetails}; use gfx::display_list::{BorderDisplayItem, ImageBorder, NormalBorder}; use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClippingRegion}; use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayList, DisplayListSection}; -use gfx::display_list::{GradientDisplayItem, IframeDisplayItem, ImageDisplayItem}; +use gfx::display_list::{GradientDisplayItem, RadialGradientDisplayItem, IframeDisplayItem, ImageDisplayItem}; use gfx::display_list::{LineDisplayItem, OpaqueNode}; use gfx::display_list::{SolidColorDisplayItem, ScrollRoot, StackingContext, StackingContextType}; use gfx::display_list::{TextDisplayItem, TextOrientation, WebGLDisplayItem, WebRenderImageInfo}; @@ -33,7 +33,7 @@ use gfx_traits::{combine_id_with_fragment_type, FragmentType, StackingContextId} use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT}; use ipc_channel::ipc; use list_item::ListItemFlow; -use model::{self, MaybeAuto}; +use model::{self, MaybeAuto, specified}; use msg::constellation_msg::PipelineId; use net_traits::image::base::PixelFormat; use net_traits::image_cache::UsePlaceholder; @@ -58,8 +58,10 @@ use style::properties::longhands::border_image_repeat::computed_value::RepeatKey use style::properties::style_structs; use style::servo::restyle_damage::REPAINT; use style::values::{Either, RGBA, computed}; -use style::values::computed::{AngleOrCorner, Gradient, GradientItem, GradientKind}; -use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto, NumberOrPercentage}; +use style::values::computed::{AngleOrCorner, Gradient, GradientItem, GradientKind, LengthOrPercentage}; +use style::values::computed::{LengthOrPercentageOrAuto, LengthOrKeyword, LengthOrPercentageOrKeyword}; +use style::values::computed::{NumberOrPercentage, Position}; +use style::values::computed::image::{EndingShape, SizeKeyword}; use style::values::specified::{HorizontalDirection, VerticalDirection}; use style_traits::CSSPixel; use style_traits::cursor::Cursor; @@ -385,11 +387,22 @@ pub trait FragmentDisplayListBuilding { image_url: &ServoUrl, background_index: usize); - fn convert_gradient(&self, - absolute_bounds: &Rect, - gradient: &Gradient, - style: &ServoComputedValues) - -> Option; + fn convert_linear_gradient(&self, + bounds: &Rect, + stops: &[GradientItem], + angle_or_corner: &AngleOrCorner, + repeating: bool, + style: &ServoComputedValues) + -> display_list::Gradient; + + fn convert_radial_gradient(&self, + bounds: &Rect, + stops: &[GradientItem], + shape: &EndingShape, + center: &Position, + repeating: bool, + style: &ServoComputedValues) + -> display_list::RadialGradient; /// Adds the display items necessary to paint the background linear gradient of this fragment /// to the appropriate section of the display list. @@ -397,6 +410,7 @@ pub trait FragmentDisplayListBuilding { state: &mut DisplayListBuildState, display_list_section: DisplayListSection, absolute_bounds: &Rect, + clip_bounds: &Rect, clip: &ClippingRegion, gradient: &Gradient, style: &ServoComputedValues); @@ -588,6 +602,152 @@ fn build_border_radius_for_inner_rect(outer_rect: &Rect, radii } +fn convert_gradient_stops(gradient_items: &[GradientItem], + length: Au, + style: &ServoComputedValues) -> Vec { + // Determine the position of each stop per CSS-IMAGES § 3.4. + // + // FIXME(#3908, pcwalton): Make sure later stops can't be behind earlier stops. + let stop_items = gradient_items.iter().filter_map(|item| { + match *item { + GradientItem::ColorStop(ref stop) => Some(stop), + _ => None, + } + }).collect::>(); + let mut stops = Vec::with_capacity(stop_items.len()); + let mut stop_run = None; + for (i, stop) in stop_items.iter().enumerate() { + let offset = match stop.position { + None => { + if stop_run.is_none() { + // Initialize a new stop run. + let start_offset = if i == 0 { + 0.0 + } else { + // `unwrap()` here should never fail because this is the beginning of + // a stop run, which is always bounded by a length or percentage. + position_to_offset(stop_items[i - 1].position.unwrap(), length) + }; + let (end_index, end_offset) = + match stop_items[i..] + .iter() + .enumerate() + .find(|&(_, ref stop)| stop.position.is_some()) { + None => (stop_items.len() - 1, 1.0), + Some((end_index, end_stop)) => { + // `unwrap()` here should never fail because this is the end of + // a stop run, which is always bounded by a length or + // percentage. + (end_index, + position_to_offset(end_stop.position.unwrap(), length)) + } + }; + stop_run = Some(StopRun { + start_offset: start_offset, + end_offset: end_offset, + start_index: i, + stop_count: end_index - i, + }) + } + + let stop_run = stop_run.unwrap(); + let stop_run_length = stop_run.end_offset - stop_run.start_offset; + if stop_run.stop_count == 0 { + stop_run.end_offset + } else { + stop_run.start_offset + + stop_run_length * (i - stop_run.start_index) as f32 / + (stop_run.stop_count as f32) + } + } + Some(position) => { + stop_run = None; + position_to_offset(position, length) + } + }; + stops.push(GradientStop { + offset: offset, + color: style.resolve_color(stop.color).to_gfx_color() + }) + } + stops +} + +/// Returns the the distance to the nearest or farthest corner depending on the comperator. +fn get_distance_to_corner(size: &Size2D, center: &Point2D, cmp: F) -> Au + where F: Fn(Au, Au) -> Au +{ + let dist = get_distance_to_sides(size, center, cmp); + Au::from_f32_px(dist.width.to_f32_px().hypot(dist.height.to_f32_px())) +} + +/// Returns the distance to the nearest or farthest sides depending on the comparator. +/// +/// The first return value is horizontal distance the second vertical distance. +fn get_distance_to_sides(size: &Size2D, center: &Point2D, cmp: F) -> Size2D + where F: Fn(Au, Au) -> Au +{ + let top_side = center.y; + let right_side = size.width - center.x; + let bottom_side = size.height - center.y; + let left_side = center.x; + Size2D::new(cmp(left_side, right_side), cmp(top_side, bottom_side)) +} + +/// Returns the radius for an ellipse with the same ratio as if it was matched to the sides. +fn get_ellipse_radius(size: &Size2D, center: &Point2D, cmp: F) -> Size2D + where F: Fn(Au, Au) -> Au +{ + let dist = get_distance_to_sides(size, center, cmp); + Size2D::new(dist.width.scale_by(::std::f32::consts::FRAC_1_SQRT_2 * 2.0), + dist.height.scale_by(::std::f32::consts::FRAC_1_SQRT_2 * 2.0)) +} + +/// Determines the radius of a circle if it was not explictly provided. +/// https://drafts.csswg.org/css-images-3/#typedef-size +fn convert_circle_size_keyword(keyword: SizeKeyword, + size: &Size2D, + center: &Point2D) -> Size2D { + use style::values::computed::image::SizeKeyword::*; + let radius = match keyword { + ClosestSide => { + let dist = get_distance_to_sides(size, center, ::std::cmp::min); + ::std::cmp::min(dist.width, dist.height) + } + FarthestSide => { + let dist = get_distance_to_sides(size, center, ::std::cmp::max); + ::std::cmp::max(dist.width, dist.height) + } + ClosestCorner => get_distance_to_corner(size, center, ::std::cmp::min), + FarthestCorner => get_distance_to_corner(size, center, ::std::cmp::max), + _ => { + // TODO(#16542) + println!("TODO: implement size keyword {:?} for circles", keyword); + Au::new(0) + } + }; + Size2D::new(radius, radius) +} + +/// Determines the radius of an ellipse if it was not explictly provided. +/// https://drafts.csswg.org/css-images-3/#typedef-size +fn convert_ellipse_size_keyword(keyword: SizeKeyword, + size: &Size2D, + center: &Point2D) -> Size2D { + use style::values::computed::image::SizeKeyword::*; + match keyword { + ClosestSide => get_distance_to_sides(size, center, ::std::cmp::min), + FarthestSide => get_distance_to_sides(size, center, ::std::cmp::max), + ClosestCorner => get_ellipse_radius(size, center, ::std::cmp::min), + FarthestCorner => get_ellipse_radius(size, center, ::std::cmp::max), + _ => { + // TODO(#16542) + println!("TODO: implement size keyword {:?} for ellipses", keyword); + Size2D::new(Au::new(0), Au::new(0)) + } + } +} + impl FragmentDisplayListBuilding for Fragment { fn build_display_list_for_background_if_applicable(&self, state: &mut DisplayListBuildState, @@ -653,15 +813,13 @@ impl FragmentDisplayListBuilding for Fragment { match background_image.0 { None => {} Some(computed::Image::Gradient(ref gradient)) => { - // FIXME: Radial gradients aren't implemented yet. - if let GradientKind::Linear(_) = gradient.gradient_kind { - self.build_display_list_for_background_gradient(state, - display_list_section, - &bounds, - &clip, - gradient, - style); - } + self.build_display_list_for_background_gradient(state, + display_list_section, + &absolute_bounds, + &bounds, + &clip, + gradient, + style); } Some(computed::Image::Url(ref image_url)) => { if let Some(url) = image_url.url() { @@ -893,46 +1051,40 @@ impl FragmentDisplayListBuilding for Fragment { } } - fn convert_gradient(&self, - absolute_bounds: &Rect, - gradient: &Gradient, - style: &ServoComputedValues) -> Option { - // FIXME: Repeating gradients aren't implemented yet. - if gradient.repeating { - return None; - } - let angle = if let GradientKind::Linear(angle_or_corner) = gradient.gradient_kind { - match angle_or_corner { - AngleOrCorner::Angle(angle) => angle.radians(), - AngleOrCorner::Corner(horizontal, vertical) => { - // This the angle for one of the diagonals of the box. Our angle - // will either be this one, this one + PI, or one of the other - // two perpendicular angles. - let atan = (absolute_bounds.size.height.to_f32_px() / - absolute_bounds.size.width.to_f32_px()).atan(); - match (horizontal, vertical) { - (HorizontalDirection::Right, VerticalDirection::Bottom) - => f32::consts::PI - atan, - (HorizontalDirection::Left, VerticalDirection::Bottom) - => f32::consts::PI + atan, - (HorizontalDirection::Right, VerticalDirection::Top) - => atan, - (HorizontalDirection::Left, VerticalDirection::Top) - => -atan, - } + fn convert_linear_gradient(&self, + bounds: &Rect, + stops: &[GradientItem], + angle_or_corner: &AngleOrCorner, + repeating: bool, + style: &ServoComputedValues) + -> display_list::Gradient { + let angle = match *angle_or_corner { + AngleOrCorner::Angle(angle) => angle.radians(), + AngleOrCorner::Corner(horizontal, vertical) => { + // This the angle for one of the diagonals of the box. Our angle + // will either be this one, this one + PI, or one of the other + // two perpendicular angles. + let atan = (bounds.size.height.to_f32_px() / + bounds.size.width.to_f32_px()).atan(); + match (horizontal, vertical) { + (HorizontalDirection::Right, VerticalDirection::Bottom) + => f32::consts::PI - atan, + (HorizontalDirection::Left, VerticalDirection::Bottom) + => f32::consts::PI + atan, + (HorizontalDirection::Right, VerticalDirection::Top) + => atan, + (HorizontalDirection::Left, VerticalDirection::Top) + => -atan, } } - } else { - // FIXME: Radial gradients aren't implemented yet. - return None; }; // Get correct gradient line length, based on: // https://drafts.csswg.org/css-images-3/#linear-gradients let dir = Point2D::new(angle.sin(), -angle.cos()); - let line_length = (dir.x * absolute_bounds.size.width.to_f32_px()).abs() + - (dir.y * absolute_bounds.size.height.to_f32_px()).abs(); + let line_length = (dir.x * bounds.size.width.to_f32_px()).abs() + + (dir.y * bounds.size.height.to_f32_px()).abs(); let inv_dir_length = 1.0 / (dir.x * dir.x + dir.y * dir.y).sqrt(); @@ -945,108 +1097,100 @@ impl FragmentDisplayListBuilding for Fragment { let length = Au::from_f32_px( (delta.x.to_f32_px() * 2.0).hypot(delta.y.to_f32_px() * 2.0)); - // Determine the position of each stop per CSS-IMAGES § 3.4. - // - // FIXME(#3908, pcwalton): Make sure later stops can't be behind earlier stops. - let stop_items = gradient.items.iter().filter_map(|item| { - match *item { - GradientItem::ColorStop(ref stop) => Some(stop), - _ => None, - } - }).collect::>(); - let mut stops = Vec::with_capacity(stop_items.len()); - let mut stop_run = None; - for (i, stop) in stop_items.iter().enumerate() { - let offset = match stop.position { - None => { - if stop_run.is_none() { - // Initialize a new stop run. - let start_offset = if i == 0 { - 0.0 - } else { - // `unwrap()` here should never fail because this is the beginning of - // a stop run, which is always bounded by a length or percentage. - position_to_offset(stop_items[i - 1].position.unwrap(), length) - }; - let (end_index, end_offset) = - match stop_items[i..] - .iter() - .enumerate() - .find(|&(_, ref stop)| stop.position.is_some()) { - None => (stop_items.len() - 1, 1.0), - Some((end_index, end_stop)) => { - // `unwrap()` here should never fail because this is the end of - // a stop run, which is always bounded by a length or - // percentage. - (end_index, - position_to_offset(end_stop.position.unwrap(), length)) - } - }; - stop_run = Some(StopRun { - start_offset: start_offset, - end_offset: end_offset, - start_index: i, - stop_count: end_index - i, - }) - } + let stops = convert_gradient_stops(stops, length, style); - let stop_run = stop_run.unwrap(); - let stop_run_length = stop_run.end_offset - stop_run.start_offset; - if stop_run.stop_count == 0 { - stop_run.end_offset - } else { - stop_run.start_offset + - stop_run_length * (i - stop_run.start_index) as f32 / - (stop_run.stop_count as f32) - } - } - Some(position) => { - stop_run = None; - position_to_offset(position, length) - } - }; - stops.push(GradientStop { - offset: offset, - color: style.resolve_color(stop.color).to_gfx_color() - }) - } + let center = Point2D::new(bounds.size.width / 2, bounds.size.height / 2); - let center = Point2D::new(absolute_bounds.size.width / 2, - absolute_bounds.size.height / 2); - - Some(display_list::Gradient { + display_list::Gradient { start_point: center - delta, end_point: center + delta, stops: stops, - }) + repeating: repeating, + } + } + + fn convert_radial_gradient(&self, + bounds: &Rect, + stops: &[GradientItem], + shape: &EndingShape, + center: &Position, + repeating: bool, + style: &ServoComputedValues) + -> display_list::RadialGradient { + let center = Point2D::new(specified(center.horizontal.0, bounds.size.width), + specified(center.vertical.0, bounds.size.height)); + let radius = match *shape { + EndingShape::Circle(LengthOrKeyword::Length(length)) + => Size2D::new(length, length), + EndingShape::Circle(LengthOrKeyword::Keyword(word)) + => convert_circle_size_keyword(word, &bounds.size, ¢er), + EndingShape::Ellipse(LengthOrPercentageOrKeyword::LengthOrPercentage(horizontal, + vertical)) + => Size2D::new(specified(horizontal, bounds.size.width), + specified(vertical, bounds.size.height)), + EndingShape::Ellipse(LengthOrPercentageOrKeyword::Keyword(word)) + => convert_ellipse_size_keyword(word, &bounds.size, ¢er), + }; + let length = Au::from_f32_px(radius.width.to_f32_px().hypot(radius.height.to_f32_px())); + let stops = convert_gradient_stops(stops, length, style); + display_list::RadialGradient { + center: center, + radius: radius, + stops: stops, + repeating: repeating, + } } fn build_display_list_for_background_gradient(&self, state: &mut DisplayListBuildState, display_list_section: DisplayListSection, absolute_bounds: &Rect, + clip_bounds: &Rect, clip: &ClippingRegion, gradient: &Gradient, style: &ServoComputedValues) { let mut clip = clip.clone(); - clip.intersect_rect(absolute_bounds); + clip.intersect_rect(clip_bounds); - let grad = self.convert_gradient(absolute_bounds, gradient, style); + let border_padding = self.border_padding.to_physical(style.writing_mode); + let mut bounds = *absolute_bounds; + bounds.origin.x = bounds.origin.x + border_padding.left; + bounds.origin.y = bounds.origin.y + border_padding.top; + bounds.size.width = bounds.size.width - border_padding.horizontal(); + bounds.size.height = bounds.size.height - border_padding.vertical(); - if let Some(x) = grad { - let base = state.create_base_display_item(absolute_bounds, - &clip, - self.node, - style.get_cursor(Cursor::Default), - display_list_section); + let base = state.create_base_display_item(&bounds, + &clip, + self.node, + style.get_cursor(Cursor::Default), + display_list_section); - let gradient_display_item = DisplayItem::Gradient(box GradientDisplayItem { - base: base, - gradient: x, - }); - - state.add_display_item(gradient_display_item); - } + let display_item = match gradient.gradient_kind { + GradientKind::Linear(ref angle_or_corner) => { + let gradient = self.convert_linear_gradient(&bounds, + &gradient.items[..], + angle_or_corner, + gradient.repeating, + style); + DisplayItem::Gradient(box GradientDisplayItem { + base: base, + gradient: gradient, + }) + } + GradientKind::Radial(ref shape, ref center) => { + let gradient = self.convert_radial_gradient(&bounds, + &gradient.items[..], + shape, + center, + gradient.repeating, + style); + DisplayItem::RadialGradient(box RadialGradientDisplayItem { + base: base, + gradient: gradient, + }) + } + }; + state.add_display_item(display_item); } fn build_display_list_for_box_shadow_if_applicable(&self, @@ -1159,24 +1303,26 @@ impl FragmentDisplayListBuilding for Fragment { } Some(computed::Image::Gradient(ref gradient)) => { match gradient.gradient_kind { - GradientKind::Linear(_) => { - let grad = self.convert_gradient(&bounds, gradient, style); + GradientKind::Linear(angle_or_corner) => { + let grad = self.convert_linear_gradient(&bounds, + &gradient.items[..], + &angle_or_corner, + gradient.repeating, + style); - if let Some(x) = grad { - state.add_display_item(DisplayItem::Border(box BorderDisplayItem { - base: base, - border_widths: border.to_physical(style.writing_mode), - details: BorderDetails::Gradient(display_list::GradientBorder { - gradient: x, + state.add_display_item(DisplayItem::Border(box BorderDisplayItem { + base: base, + border_widths: border.to_physical(style.writing_mode), + details: BorderDetails::Gradient(display_list::GradientBorder { + gradient: grad, - // TODO(gw): Support border-image-outset - outset: SideOffsets2D::zero(), - }), - })); - } + // TODO(gw): Support border-image-outset + outset: SideOffsets2D::zero(), + }), + })); } GradientKind::Radial(_, _) => { - // TODO(gw): Handle border-image with radial gradient. + // TODO(#16638): Handle border-image with radial gradient. } } } diff --git a/servo/components/layout/webrender_helpers.rs b/servo/components/layout/webrender_helpers.rs index 723e33287024..70479d438379 100644 --- a/servo/components/layout/webrender_helpers.rs +++ b/servo/components/layout/webrender_helpers.rs @@ -370,16 +370,41 @@ impl WebRenderDisplayItemConverter for DisplayItem { let start_point = item.gradient.start_point.to_pointf(); let end_point = item.gradient.end_point.to_pointf(); let clip = item.base.clip.to_clip_region(builder); + let extend_mode = if item.gradient.repeating { + ExtendMode::Repeat + } else { + ExtendMode::Clamp + }; let gradient = builder.create_gradient(start_point, end_point, item.gradient.stops.clone(), - ExtendMode::Clamp); + extend_mode); builder.push_gradient(rect, clip, gradient, rect.size, webrender_traits::LayoutSize::zero()); } + DisplayItem::RadialGradient(ref item) => { + let rect = item.base.bounds.to_rectf(); + let center = item.gradient.center.to_pointf(); + let radius = item.gradient.radius.to_sizef(); + let clip = item.base.clip.to_clip_region(builder); + let extend_mode = if item.gradient.repeating { + ExtendMode::Repeat + } else { + ExtendMode::Clamp + }; + let gradient = builder.create_radial_gradient(center, + radius, + item.gradient.stops.clone(), + extend_mode); + builder.push_radial_gradient(rect, + clip, + gradient, + rect.size, + webrender_traits::LayoutSize::zero()); + } DisplayItem::Line(..) => { println!("TODO DisplayItem::Line"); } diff --git a/servo/components/script/dom/canvasrenderingcontext2d.rs b/servo/components/script/dom/canvasrenderingcontext2d.rs index 432dbe800aa8..a5ec8d233b65 100644 --- a/servo/components/script/dom/canvasrenderingcontext2d.rs +++ b/servo/components/script/dom/canvasrenderingcontext2d.rs @@ -350,7 +350,7 @@ impl CanvasRenderingContext2D { dh); if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) { - return Err(Error::IndexSize); + return Ok(()); } let smoothing_enabled = self.state.borrow().image_smoothing_enabled; @@ -407,7 +407,7 @@ impl CanvasRenderingContext2D { dh); if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) { - return Err(Error::IndexSize); + return Ok(()); } let smoothing_enabled = self.state.borrow().image_smoothing_enabled; diff --git a/servo/components/selectors/parser.rs b/servo/components/selectors/parser.rs index f53380c2b220..66867000fda0 100644 --- a/servo/components/selectors/parser.rs +++ b/servo/components/selectors/parser.rs @@ -1457,7 +1457,7 @@ pub mod tests { where V: SelectorVisitor { true } } - #[derive(PartialEq, Debug)] + #[derive(Clone, PartialEq, Debug)] pub struct DummySelectorImpl; #[derive(Default)] diff --git a/servo/components/style/properties/gecko.mako.rs b/servo/components/style/properties/gecko.mako.rs index b468a76009d1..b8f4d4ed5418 100644 --- a/servo/components/style/properties/gecko.mako.rs +++ b/servo/components/style/properties/gecko.mako.rs @@ -3784,8 +3784,8 @@ clip-path for (mut gecko, servo) in self.gecko.mStrokeDasharray.iter_mut().zip(v.0.into_iter()) { match servo { - Either::First(lop) => gecko.set(lop), - Either::Second(number) => gecko.set_value(CoordDataValue::Factor(number)), + Either::First(number) => gecko.set_value(CoordDataValue::Factor(number)), + Either::Second(lop) => gecko.set(lop), } } } diff --git a/servo/components/style/properties/longhand/box.mako.rs b/servo/components/style/properties/longhand/box.mako.rs index 85350c76ddf3..bd53e8c716db 100644 --- a/servo/components/style/properties/longhand/box.mako.rs +++ b/servo/components/style/properties/longhand/box.mako.rs @@ -2008,8 +2008,8 @@ ${helpers.predefined_type("scroll-snap-coordinate", m32: Number::from_computed_value(&computed.m32), m33: Number::from_computed_value(&computed.m33), m34: Number::from_computed_value(&computed.m34), - m41: Either::First(LengthOrPercentage::from_computed_value(&computed.m41)), - m42: Either::First(LengthOrPercentage::from_computed_value(&computed.m42)), + m41: Either::Second(LengthOrPercentage::from_computed_value(&computed.m41)), + m42: Either::Second(LengthOrPercentage::from_computed_value(&computed.m42)), m43: LengthOrNumber::from_computed_value(&Either::First(computed.m43)), m44: Number::from_computed_value(&computed.m44), }); @@ -2056,8 +2056,8 @@ ${helpers.predefined_type("scroll-snap-coordinate", // LengthOrPercentage. Number maps into Length fn lopon_to_lop(value: &ComputedLoPoNumber) -> ComputedLoP { match *value { - Either::First(length_or_percentage) => length_or_percentage, - Either::Second(number) => ComputedLoP::Length(Au::from_f32_px(number)), + Either::First(number) => ComputedLoP::Length(Au::from_f32_px(number)), + Either::Second(length_or_percentage) => length_or_percentage, } } diff --git a/servo/components/style/properties/longhand/inherited_svg.mako.rs b/servo/components/style/properties/longhand/inherited_svg.mako.rs index 480f4a7adfb1..068c3d127f61 100644 --- a/servo/components/style/properties/longhand/inherited_svg.mako.rs +++ b/servo/components/style/properties/longhand/inherited_svg.mako.rs @@ -92,7 +92,7 @@ ${helpers.predefined_type("stroke-opacity", "Opacity", "1.0", ${helpers.predefined_type("stroke-dasharray", "LengthOrPercentageOrNumber", - "Either::Second(0.0)", + "Either::First(0.0)", "parse_non_negative", vector="True", allow_empty="True", diff --git a/servo/components/style/restyle_hints.rs b/servo/components/style/restyle_hints.rs index 9d3d8814ac76..193b7e82a9da 100644 --- a/servo/components/style/restyle_hints.rs +++ b/servo/components/style/restyle_hints.rs @@ -18,7 +18,7 @@ use selectors::{Element, MatchAttr}; use selectors::matching::{ElementSelectorFlags, StyleRelations}; use selectors::matching::matches_selector; use selectors::parser::{AttrSelector, Combinator, Component, Selector}; -use selectors::parser::{SelectorInner, SelectorIter, SelectorMethods}; +use selectors::parser::{SelectorInner, SelectorMethods}; use selectors::visitor::SelectorVisitor; use std::clone::Clone; @@ -482,27 +482,13 @@ struct Dependency { /// of them is sensitive to attribute or state changes. struct SensitivitiesVisitor { sensitivities: Sensitivities, - hint: RestyleHint, } impl SelectorVisitor for SensitivitiesVisitor { type Impl = SelectorImpl; - - fn visit_complex_selector(&mut self, - _: SelectorIter, - combinator: Option) -> bool { - self.hint |= combinator_to_restyle_hint(combinator); - - true - } - fn visit_simple_selector(&mut self, s: &Component) -> bool { self.sensitivities.states.insert(selector_to_state(s)); - - if !self.sensitivities.attrs { - self.sensitivities.attrs = is_attr_selector(s); - } - + self.sensitivities.attrs |= is_attr_selector(s); true } } @@ -539,56 +525,63 @@ impl DependencySet { /// Adds a selector to this `DependencySet`. pub fn note_selector(&mut self, selector: &Selector) { - let mut is_pseudo_element = selector.pseudo_element.is_some(); - - let mut next = Some(selector.inner.complex.clone()); let mut combinator = None; + let mut iter = selector.inner.complex.iter(); + let mut index = 0; - while let Some(current) = next.take() { - // Set up our visitor. + loop { + let sequence_start = index; let mut visitor = SensitivitiesVisitor { - sensitivities: Sensitivities::new(), - hint: combinator_to_restyle_hint(combinator), + sensitivities: Sensitivities::new() }; - if is_pseudo_element { - // TODO(emilio): use more fancy restyle hints to avoid restyling - // the whole subtree when pseudos change. - // - // We currently need is_pseudo_element to handle eager pseudos - // (so the style the parent stores doesn't become stale), and - // restyle_descendants to handle all of them (::before and - // ::after, because we find them in the subtree, and other lazy - // pseudos for the same reason). - visitor.hint |= RESTYLE_SELF | RESTYLE_DESCENDANTS; - is_pseudo_element = false; + // Visit all the simple selectors in this sequence. + // + // Note that this works because we can't have combinators nested + // inside simple selectors (i.e. in :not() or :-moz-any()). If we + // ever support that we'll need to visit complex selectors as well. + for ss in &mut iter { + ss.visit(&mut visitor); + index += 1; // Account for the simple selector. } - { - // Visit all the simple selectors. - let mut iter = current.iter(); - let mut index = 0usize; - for ss in &mut iter { - ss.visit(&mut visitor); - index += 1; - } - - // Prepare the next sequence of simple selectors. - if let Some(next_combinator) = iter.next_sequence() { - next = Some(current.slice_from(index + 1)); - combinator = Some(next_combinator); - } - } - - // Note what we found. + // If we found a sensitivity, add an entry in the dependency set. if !visitor.sensitivities.is_empty() { + let mut hint = combinator_to_restyle_hint(combinator); + let dep_selector; + if sequence_start == 0 { + if selector.pseudo_element.is_some() { + // TODO(emilio): use more fancy restyle hints to avoid + // restyling the whole subtree when pseudos change. + // + // We currently need is_pseudo_element to handle eager + // pseudos (so the style the parent stores doesn't + // become stale), and restyle_descendants to handle all + // of them (::before and ::after, because we find them + // in the subtree, and other lazy pseudos for the same + // reason). + hint |= RESTYLE_SELF | RESTYLE_DESCENDANTS; + } + + // Reuse the bloom hashes if this is the base selector. + dep_selector = selector.inner.clone(); + } else { + dep_selector = SelectorInner::new(selector.inner.complex.slice_from(sequence_start)); + } + self.add_dependency(Dependency { sensitivities: visitor.sensitivities, - hint: visitor.hint, - selector: SelectorInner::new(current), - }) + hint: hint, + selector: dep_selector, + }); } + combinator = iter.next_sequence(); + if combinator.is_none() { + break; + } + + index += 1; // Account for the combinator. } } diff --git a/servo/components/style/stylist.rs b/servo/components/style/stylist.rs index cde51a8f3fbe..65d04630fd35 100644 --- a/servo/components/style/stylist.rs +++ b/servo/components/style/stylist.rs @@ -313,38 +313,13 @@ impl Stylist { CssRule::Style(ref locked) => { let style_rule = locked.read_with(&guard); self.num_declarations += style_rule.block.read_with(&guard).len(); - for selector in &style_rule.selectors.0 { self.num_selectors += 1; - let map = if let Some(ref pseudo) = selector.pseudo_element { - self.pseudos_map - .entry(pseudo.clone()) - .or_insert_with(PerPseudoElementSelectorMap::new) - .borrow_for_origin(&stylesheet.origin) - } else { - self.element_map.borrow_for_origin(&stylesheet.origin) - }; - - map.insert(Rule::new(guard, - selector.inner.clone(), - locked.clone(), - self.rules_source_order, - selector.specificity)); + self.add_rule_to_map(guard, selector, locked, stylesheet); + self.dependencies.note_selector(selector); + self.note_for_revalidation(selector); } self.rules_source_order += 1; - - for selector in &style_rule.selectors.0 { - self.dependencies.note_selector(selector); - - if needs_revalidation(selector) { - // For revalidation, we can skip everything left of - // the first ancestor combinator. - let revalidation_sel = - selector.inner.slice_to_first_ancestor_combinator(); - - self.selectors_for_cache_revalidation.push(revalidation_sel); - } - } } CssRule::Import(ref import) => { let import = import.read_with(guard); @@ -374,6 +349,38 @@ impl Stylist { }); } + #[inline] + fn add_rule_to_map(&mut self, + guard: &SharedRwLockReadGuard, + selector: &Selector, + rule: &Arc>, + stylesheet: &Stylesheet) + { + let map = if let Some(ref pseudo) = selector.pseudo_element { + self.pseudos_map + .entry(pseudo.clone()) + .or_insert_with(PerPseudoElementSelectorMap::new) + .borrow_for_origin(&stylesheet.origin) + } else { + self.element_map.borrow_for_origin(&stylesheet.origin) + }; + + map.insert(Rule::new(guard, + selector.inner.clone(), + rule.clone(), + self.rules_source_order, + selector.specificity)); + } + + #[inline] + fn note_for_revalidation(&mut self, selector: &Selector) { + if needs_revalidation(selector) { + // For revalidation, we can skip everything left of the first ancestor + // combinator. + let revalidation_sel = selector.inner.slice_to_first_ancestor_combinator(); + self.selectors_for_cache_revalidation.push(revalidation_sel); + } + } /// Computes the style for a given "precomputed" pseudo-element, taking the /// universal rules and applying them. @@ -1043,9 +1050,6 @@ pub struct SelectorMap { pub class_hash: FnvHashMap>, /// A hash from local name to rules which contain that local name selector. pub local_name_hash: FnvHashMap>, - /// Same as local_name_hash, but keys are lower-cased. - /// For HTML elements in HTML documents. - pub lower_local_name_hash: FnvHashMap>, /// Rules that don't have ID, class, or element selectors. pub other_rules: Vec, /// Whether this hash is empty. @@ -1064,7 +1068,6 @@ impl SelectorMap { id_hash: HashMap::default(), class_hash: HashMap::default(), local_name_hash: HashMap::default(), - lower_local_name_hash: HashMap::default(), other_rules: Vec::new(), empty: true, } @@ -1113,14 +1116,9 @@ impl SelectorMap { cascade_level); }); - let local_name_hash = if element.is_html_element_in_html_document() { - &self.lower_local_name_hash - } else { - &self.local_name_hash - }; SelectorMap::get_matching_rules_from_hash(element, parent_bf, - local_name_hash, + &self.local_name_hash, element.get_local_name(), matching_rules_list, relations, @@ -1253,8 +1251,22 @@ impl SelectorMap { } if let Some(LocalNameSelector { name, lower_name }) = SelectorMap::get_local_name(&rule) { - find_push(&mut self.local_name_hash, name, rule.clone()); - find_push(&mut self.lower_local_name_hash, lower_name, rule); + // If the local name in the selector isn't lowercase, insert it into + // the rule hash twice. This means that, during lookup, we can always + // find the rules based on the local name of the element, regardless + // of whether it's an html element in an html document (in which case + // we match against lower_name) or not (in which case we match against + // name). + // + // In the case of a non-html-element-in-html-document with a + // lowercase localname and a non-lowercase selector, the rulehash + // lookup may produce superfluous selectors, but the subsequent + // selector matching work will filter them out. + if name != lower_name { + find_push(&mut self.local_name_hash, lower_name, rule.clone()); + } + find_push(&mut self.local_name_hash, name, rule); + return; } diff --git a/servo/components/style/values/computed/image.rs b/servo/components/style/values/computed/image.rs index 4ccce1e1f8f9..607cc8f20257 100644 --- a/servo/components/style/values/computed/image.rs +++ b/servo/components/style/values/computed/image.rs @@ -14,10 +14,11 @@ use std::fmt; use style_traits::ToCss; use values::computed::{Angle, Context, Length, LengthOrPercentage, NumberOrPercentage, ToComputedValue}; use values::computed::position::Position; -use values::specified::{self, HorizontalDirection, SizeKeyword, VerticalDirection}; +use values::specified::{self, HorizontalDirection, VerticalDirection}; use values::specified::image::CompatMode; use values::specified::url::SpecifiedUrl; +pub use values::specified::SizeKeyword; impl ToComputedValue for specified::Image { type ComputedValue = Image; diff --git a/servo/components/style/values/computed/mod.rs b/servo/components/style/values/computed/mod.rs index 9f7396608779..7cfdfa777163 100644 --- a/servo/components/style/values/computed/mod.rs +++ b/servo/components/style/values/computed/mod.rs @@ -468,7 +468,7 @@ impl ToCss for SVGPaint { } /// | | -pub type LengthOrPercentageOrNumber = Either; +pub type LengthOrPercentageOrNumber = Either; #[derive(Clone, PartialEq, Eq, Copy, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] diff --git a/servo/components/style/values/specified/mod.rs b/servo/components/style/values/specified/mod.rs index c51027b864ae..84c25c81119b 100644 --- a/servo/components/style/values/specified/mod.rs +++ b/servo/components/style/values/specified/mod.rs @@ -1191,7 +1191,7 @@ impl ToComputedValue for SVGPaintKind { } /// | | -pub type LengthOrPercentageOrNumber = Either; +pub type LengthOrPercentageOrNumber = Either; impl LengthOrPercentageOrNumber { /// parse a | enforcing that the contents aren't negative @@ -1199,10 +1199,10 @@ impl LengthOrPercentageOrNumber { // NB: Parse numbers before Lengths so we are consistent about how to // recognize and serialize "0". if let Ok(num) = input.try(|i| Number::parse_non_negative(context, i)) { - return Ok(Either::Second(num)) + return Ok(Either::First(num)) } - LengthOrPercentage::parse_non_negative(context, input).map(Either::First) + LengthOrPercentage::parse_non_negative(context, input).map(Either::Second) } } diff --git a/servo/tests/unit/style/parsing/length.rs b/servo/tests/unit/style/parsing/length.rs index b6d9a30b42c5..6b2464849349 100644 --- a/servo/tests/unit/style/parsing/length.rs +++ b/servo/tests/unit/style/parsing/length.rs @@ -8,6 +8,8 @@ use parsing::parse; use style::context::QuirksMode; use style::parser::{LengthParsingMode, Parse, ParserContext}; use style::stylesheets::{CssRuleType, Origin}; +use style::values::Either; +use style::values::specified::{LengthOrPercentageOrNumber, Number}; use style::values::specified::length::{AbsoluteLength, Length, NoCalcLength}; use style_traits::ToCss; @@ -46,3 +48,8 @@ fn test_length_parsing_modes() { assert!(result.is_ok()); assert_eq!(result.unwrap(), Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(1.)))); } + +#[test] +fn test_zero_percentage_length_or_number() { + assert_eq!(parse(LengthOrPercentageOrNumber::parse, "0"), Ok(Either::First(Number::new(0.)))); +} diff --git a/testing/web-platform/tests/dom/nodes/DOMImplementation-createDocumentType.html b/testing/web-platform/tests/dom/nodes/DOMImplementation-createDocumentType.html index ac79ddd7340a..f7e6e18b8442 100644 --- a/testing/web-platform/tests/dom/nodes/DOMImplementation-createDocumentType.html +++ b/testing/web-platform/tests/dom/nodes/DOMImplementation-createDocumentType.html @@ -80,9 +80,9 @@ test(function() { ["(", "", "", "INVALID_CHARACTER_ERR"], [")", "", "", "INVALID_CHARACTER_ERR"], ["f:oo", "", "", null], - [":foo", "", "", "NAMESPACE_ERR"], - ["foo:", "", "", "NAMESPACE_ERR"], - ["prefix::local", "", "", "NAMESPACE_ERR"], + [":foo", "", "", "INVALID_CHARACTER_ERR"], + ["foo:", "", "", "INVALID_CHARACTER_ERR"], + ["prefix::local", "", "", "INVALID_CHARACTER_ERR"], ["foo", "foo", "", null], ["foo", "", "foo", null], ["foo", "f'oo", "", null], diff --git a/testing/web-platform/tests/dom/nodes/Document-createElementNS.js b/testing/web-platform/tests/dom/nodes/Document-createElementNS.js index 1abd3330183c..bf5e12cf9518 100644 --- a/testing/web-platform/tests/dom/nodes/Document-createElementNS.js +++ b/testing/web-platform/tests/dom/nodes/Document-createElementNS.js @@ -25,11 +25,11 @@ var createElementNS_tests = [ [null, "fo o", "INVALID_CHARACTER_ERR"], [null, "-foo", "INVALID_CHARACTER_ERR"], [null, ".foo", "INVALID_CHARACTER_ERR"], - [null, ":foo", "NAMESPACE_ERR"], + [null, ":foo", "INVALID_CHARACTER_ERR"], [null, "f:oo", "NAMESPACE_ERR"], - [null, "foo:", "NAMESPACE_ERR"], - [null, "f:o:o", "NAMESPACE_ERR"], - [null, ":", "NAMESPACE_ERR"], + [null, "foo:", "INVALID_CHARACTER_ERR"], + [null, "f:o:o", "INVALID_CHARACTER_ERR"], + [null, ":", "INVALID_CHARACTER_ERR"], [null, "xml", null], [null, "xmlns", "NAMESPACE_ERR"], [null, "xmlfoo", null], @@ -38,19 +38,19 @@ var createElementNS_tests = [ [null, "xmlfoo:bar", "NAMESPACE_ERR"], [null, "null:xml", "NAMESPACE_ERR"], ["", null, null], - ["", ":foo", "NAMESPACE_ERR"], + ["", ":foo", "INVALID_CHARACTER_ERR"], ["", "f:oo", "NAMESPACE_ERR"], - ["", "foo:", "NAMESPACE_ERR"], + ["", "foo:", "INVALID_CHARACTER_ERR"], [undefined, null, null], [undefined, undefined, null], [undefined, "foo", null], [undefined, "1foo", "INVALID_CHARACTER_ERR"], [undefined, "f1oo", null], [undefined, "foo1", null], - [undefined, ":foo", "NAMESPACE_ERR"], + [undefined, ":foo", "INVALID_CHARACTER_ERR"], [undefined, "f:oo", "NAMESPACE_ERR"], - [undefined, "foo:", "NAMESPACE_ERR"], - [undefined, "f::oo", "NAMESPACE_ERR"], + [undefined, "foo:", "INVALID_CHARACTER_ERR"], + [undefined, "f::oo", "INVALID_CHARACTER_ERR"], [undefined, "xml", null], [undefined, "xmlns", "NAMESPACE_ERR"], [undefined, "xmlfoo", null], @@ -65,15 +65,15 @@ var createElementNS_tests = [ ["http://example.com/", ".foo", "INVALID_CHARACTER_ERR"], ["http://example.com/", "f1oo", null], ["http://example.com/", "foo1", null], - ["http://example.com/", ":foo", "NAMESPACE_ERR"], + ["http://example.com/", ":foo", "INVALID_CHARACTER_ERR"], ["http://example.com/", "f:oo", null], - ["http://example.com/", "f:o:o", "NAMESPACE_ERR"], - ["http://example.com/", "foo:", "NAMESPACE_ERR"], - ["http://example.com/", "f::oo", "NAMESPACE_ERR"], - ["http://example.com/", "a:0", "NAMESPACE_ERR"], + ["http://example.com/", "f:o:o", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "foo:", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "f::oo", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "a:0", "INVALID_CHARACTER_ERR"], ["http://example.com/", "0:a", "INVALID_CHARACTER_ERR"], ["http://example.com/", "a:_", null], - ["http://example.com/", "a:\u0BC6", "NAMESPACE_ERR"], + ["http://example.com/", "a:\u0BC6", "INVALID_CHARACTER_ERR"], ["http://example.com/", "\u0BC6:a", "INVALID_CHARACTER_ERR"], ["http://example.com/", "a:a\u0BC6", null], ["http://example.com/", "a\u0BC6:a", null], @@ -98,7 +98,7 @@ var createElementNS_tests = [ ["http://example.com/", "xmlns:foo", "NAMESPACE_ERR"], ["http://example.com/", "XMLNS:foo", null], ["http://example.com/", "xmlfoo:bar", null], - ["http://example.com/", "prefix::local", "NAMESPACE_ERR"], + ["http://example.com/", "prefix::local", "INVALID_CHARACTER_ERR"], ["http://example.com/", "namespaceURI:{", "INVALID_CHARACTER_ERR"], ["http://example.com/", "namespaceURI:}", "INVALID_CHARACTER_ERR"], ["http://example.com/", "namespaceURI:~", "INVALID_CHARACTER_ERR"], @@ -130,9 +130,9 @@ var createElementNS_tests = [ ["/", "1foo", "INVALID_CHARACTER_ERR"], ["/", "f1oo", null], ["/", "foo1", null], - ["/", ":foo", "NAMESPACE_ERR"], + ["/", ":foo", "INVALID_CHARACTER_ERR"], ["/", "f:oo", null], - ["/", "foo:", "NAMESPACE_ERR"], + ["/", "foo:", "INVALID_CHARACTER_ERR"], ["/", "xml", null], ["/", "xmlns", "NAMESPACE_ERR"], ["/", "xmlfoo", null], @@ -143,9 +143,9 @@ var createElementNS_tests = [ ["http://www.w3.org/XML/1998/namespace", "1foo", "INVALID_CHARACTER_ERR"], ["http://www.w3.org/XML/1998/namespace", "f1oo", null], ["http://www.w3.org/XML/1998/namespace", "foo1", null], - ["http://www.w3.org/XML/1998/namespace", ":foo", "NAMESPACE_ERR"], + ["http://www.w3.org/XML/1998/namespace", ":foo", "INVALID_CHARACTER_ERR"], ["http://www.w3.org/XML/1998/namespace", "f:oo", null], - ["http://www.w3.org/XML/1998/namespace", "foo:", "NAMESPACE_ERR"], + ["http://www.w3.org/XML/1998/namespace", "foo:", "INVALID_CHARACTER_ERR"], ["http://www.w3.org/XML/1998/namespace", "xml", null], ["http://www.w3.org/XML/1998/namespace", "xmlns", "NAMESPACE_ERR"], ["http://www.w3.org/XML/1998/namespace", "xmlfoo", null], @@ -158,9 +158,9 @@ var createElementNS_tests = [ ["http://www.w3.org/2000/xmlns/", "1foo", "INVALID_CHARACTER_ERR"], ["http://www.w3.org/2000/xmlns/", "f1oo", "NAMESPACE_ERR"], ["http://www.w3.org/2000/xmlns/", "foo1", "NAMESPACE_ERR"], - ["http://www.w3.org/2000/xmlns/", ":foo", "NAMESPACE_ERR"], + ["http://www.w3.org/2000/xmlns/", ":foo", "INVALID_CHARACTER_ERR"], ["http://www.w3.org/2000/xmlns/", "f:oo", "NAMESPACE_ERR"], - ["http://www.w3.org/2000/xmlns/", "foo:", "NAMESPACE_ERR"], + ["http://www.w3.org/2000/xmlns/", "foo:", "INVALID_CHARACTER_ERR"], ["http://www.w3.org/2000/xmlns/", "xml", "NAMESPACE_ERR"], ["http://www.w3.org/2000/xmlns/", "xmlns", null], ["http://www.w3.org/2000/xmlns/", "xmlfoo", "NAMESPACE_ERR"], @@ -172,9 +172,9 @@ var createElementNS_tests = [ ["foo:", "1foo", "INVALID_CHARACTER_ERR"], ["foo:", "f1oo", null], ["foo:", "foo1", null], - ["foo:", ":foo", "NAMESPACE_ERR"], + ["foo:", ":foo", "INVALID_CHARACTER_ERR"], ["foo:", "f:oo", null], - ["foo:", "foo:", "NAMESPACE_ERR"], + ["foo:", "foo:", "INVALID_CHARACTER_ERR"], ["foo:", "xml", null], ["foo:", "xmlns", "NAMESPACE_ERR"], ["foo:", "xmlfoo", null], diff --git a/testing/web-platform/tests/dom/nodes/attributes.html b/testing/web-platform/tests/dom/nodes/attributes.html index 8d983350df9d..d1f2aeea571f 100644 --- a/testing/web-platform/tests/dom/nodes/attributes.html +++ b/testing/web-platform/tests/dom/nodes/attributes.html @@ -130,12 +130,12 @@ test(function() { test(function() { var el = document.createElement("foo") for (var i = 0, il = invalid_qnames.length; i < il; ++i) { - assert_throws("NAMESPACE_ERR", + assert_throws("INVALID_CHARACTER_ERR", function() { el.setAttributeNS("a", invalid_qnames[i], "fail") }, "Expected exception for " + invalid_qnames[i] + ".") } }, "When qualifiedName does not match the QName production, an " + - "NAMESPACE_ERR exception is to be thrown.") + "INVALID_CHARACTER_ERR exception is to be thrown.") // Step 3 test(function() { diff --git a/toolkit/modules/tests/modules/MockDocument.jsm b/toolkit/modules/tests/modules/MockDocument.jsm index 3cae9bb910e0..a4048dac9a01 100644 --- a/toolkit/modules/tests/modules/MockDocument.jsm +++ b/toolkit/modules/tests/modules/MockDocument.jsm @@ -10,6 +10,8 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; Cu.importGlobalProperties(["URL"]); +const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {}); + const MockDocument = { /** * Create a document for the given URL containing the given HTML with the ownerDocument of all
    s having a mocked location. @@ -46,5 +48,15 @@ const MockDocument = { }); }, + createTestDocumentFromFile(aDocumentURL, aFile) { + let fileStream = Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(Ci.nsIFileInputStream); + fileStream.init(aFile, -1, -1, 0); + + let data = NetUtil.readInputStreamToString(fileStream, fileStream.available()); + + return this.createTestDocument(aDocumentURL, data); + }, + }; diff --git a/toolkit/moz.configure b/toolkit/moz.configure index 8cf76085728d..c27bb34be9cc 100644 --- a/toolkit/moz.configure +++ b/toolkit/moz.configure @@ -587,7 +587,7 @@ option('--enable-stylo', env='STYLO_ENABLED', nargs=0, # configure options. The Windows installer of LLVM/Clang doesn't provide # llvm-config, so we need both methods to support all of our tier-1 # platforms. -llvm_config = check_prog('LLVM_CONFIG', ('llvm-config-3.9', 'llvm-config',), +llvm_config = check_prog('LLVM_CONFIG', ('llvm-config-3.9', 'llvm-config39', 'llvm-config',), what='llvm-config', allow_missing=True) option('--disable-stylo-build-bindgen',