forked from mozilla/amo-validator
/
regex.py
1508 lines (1253 loc) · 65.1 KB
/
regex.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import re
from functools import wraps
from validator.constants import BUGZILLA_BUG
from validator.compat import (FX4_DEFINITION, FX5_DEFINITION, FX6_DEFINITION,
FX7_DEFINITION, FX8_DEFINITION, FX9_DEFINITION,
FX11_DEFINITION, FX12_DEFINITION, FX13_DEFINITION,
FX14_DEFINITION, FX15_DEFINITION, FX16_DEFINITION,
FX17_DEFINITION, FX18_DEFINITION, FX19_DEFINITION,
FX20_DEFINITION, FX21_DEFINITION,
TB7_DEFINITION, TB10_DEFINITION, TB11_DEFINITION,
TB12_DEFINITION, TB13_DEFINITION, TB14_DEFINITION,
TB15_DEFINITION, TB16_DEFINITION, TB17_DEFINITION,
TB18_DEFINITION, TB19_DEFINITION, TB20_DEFINITION)
from validator.contextgenerator import ContextGenerator
from markup.csstester import UNPREFIXED_MESSAGE
registered_regex_tests = []
NP_WARNING = "Network preferences may not be modified."
EUP_WARNING = "Extension update settings may not be modified."
NSINHS_LINK = ("https://developer.mozilla.org/en/XPCOM_Interface_Reference"
"/nsINavHistoryService")
TB7_LINK = "https://developer.mozilla.org/en/Thunderbird_7_for_developers"
NSIT_LINK = "https://developer.mozilla.org/en-US/docs/Using_the_Clipboard"
def run_regex_tests(document, err, filename, context=None, is_js=False):
"""Run all of the regex-based JS tests."""
if context is None:
context = ContextGenerator(document)
# Run all of the registered tests.
for cls in registered_regex_tests:
if not cls.applicable(err, filename, document):
continue
t = cls(err, document, filename, context)
# Run standard tests.
for test in t.tests():
test()
# Run tests that would otherwise be guarded by `is_js`.
if is_js:
for test in t.js_tests():
test()
def register_generator(cls):
registered_regex_tests.append(cls)
return cls
class RegexTestGenerator(object):
"""
This stubs out a test generator object. By decorating inheritors of this
class with `@register_generator`, the regex tests will be run on any files
that are passed to `run_regex_tests()`.
"""
def __init__(self, err, document, filename, context):
self.err = err
self.document = document
self.filename = filename
self.context = context
self.app_versions_fallback = None
@classmethod
def applicable(cls, err, filename, document):
"""Return whether the tests apply to the current file."""
return True # Default to always applicable.
def tests(self):
"""Override this with a generator that produces the regex tests."""
return []
def js_tests(self):
"""
Override this with a generator that produces regex tests that are
exclusive to JavaScript.
"""
return []
def get_test(self, pattern, title, message, log_function=None,
compat_type=None, app_versions=None, flags=0):
"""
Return a function that, when called, will log a compatibility warning
or error.
"""
app_versions = app_versions or self.app_versions_fallback
log_function = log_function or self.err.warning
@wraps(log_function)
def wrapper():
matched = False
for match in re.finditer(pattern, self.document, flags):
log_function(
**{'err_id': ("testcases_regex", "generic", "_generated"),
log_function.__name__: title,
'description': message,
'filename': self.filename,
'line': self.context.get_line(match.start()),
'context': self.context,
'compatibility_type': compat_type,
'for_appversions': app_versions,
'tier': self.err.tier if app_versions is None else 5})
matched = True
return matched
return wrapper
def get_test_bug(self, bug, pattern, title, message, **kwargs):
"""Helper function to mix in a bug number."""
message = [message,
"See bug %s for more information." % BUGZILLA_BUG % bug]
return self.get_test(pattern, title, message, **kwargs)
@register_generator
class GenericRegexTests(RegexTestGenerator):
"""Test for generic, banned patterns in a document being scanned."""
def tests(self):
# globalStorage.(.+)password test removed for bug 752740
yield self.get_test(
r"launch\(\)",
"`launch()` disallowed",
"Use of `launch()` is disallowed because of restrictions on "
"`nsIFile` and `nsILocalFile`. If the code does not use "
"those namespaces, consider using a different function name.")
yield self.get_test(
r"resource://services-sync",
"Sync services objects are not intended to be re-used",
"The Sync services objects are not intended to be re-used, and "
"they often change in ways that break add-ons. It is strongly "
"recommended that you do not rely on them.")
def js_tests(self):
yield self.get_test(
"mouse(move|over|out)",
"Mouse events may cause performance issues.",
"The use of `mousemove`, `mouseover`, and `mouseout` is "
"discouraged. These events are dispatched with high frequency "
"and can cause severe performance issues.",
log_function=self.err.warning)
@register_generator
class CategoryRegexTests(RegexTestGenerator):
"""
These tests will flag JavaScript category registration. Category
registration is not permitted in add-ons.
Added from bug 635423
"""
# This generates the regular expressions for all combinations of JS
# categories. Note that all of them begin with "JavaScript". Capitalization
# matters.
PATTERNS = map(lambda r: '''"%s"|'%s'|%s''' % (r, r, r.replace(" ", "-")),
["JavaScript %s" % pattern for pattern in
("global constructor",
"global constructor prototype alias",
"global property",
"global privileged property",
"global static nameset",
"global dynamic nameset",
"DOM class",
"DOM interface", )])
def js_tests(self):
for pattern in self.PATTERNS:
yield self.get_test(
pattern,
"Potential JavaScript category registration",
"Add-ons should not register JavaScript categories. It "
"appears that a JavaScript category was registered via a "
"script to attach properties to JavaScript globals. This "
"is not allowed.")
@register_generator
class DOMMutationRegexTests(RegexTestGenerator):
"""
These regex tests will test that DOM mutation events are not used. These
events have extreme performance penalties associated with them and are
currently deprecated.
Added from bug 642153
"""
EVENTS = ("DOMAttrModified", "DOMAttributeNameChanged",
"DOMCharacterDataModified", "DOMElementNameChanged",
"DOMNodeInserted", "DOMNodeInsertedIntoDocument",
"DOMNodeRemoved", "DOMNodeRemovedFromDocument",
"DOMSubtreeModified", )
def js_tests(self):
for event in self.EVENTS:
yield self.get_test(
event,
"DOM mutation event use prohibited",
"DOM mutation events are flagged because of their "
"deprecated status as well as their extreme inefficiency. "
"Consider using a different event.")
@register_generator
class MarionetteInPrefsRegexTests(RegexTestGenerator):
"""
These regex tests will ensure that the developer is not switching on
Marionette prefs
Added from bug 741812
"""
MARIONETTE_REFERENCES = {"@mozilla.org/marionette;1": 741812,
"{786a1369-dca5-4adc-8486-33d23c88010a}": 741812,
"MarionetteComponent": 741812,
"MarionetteServer": 741812}
MARIONETTE_PREFS = {"marionette.force-local": 741812,
"marionette.defaultPrefs.enabled": 741812,
"marionette.defaultPrefs.port": 741812}
@classmethod
def applicable(cls, err, filename, document):
return bool(re.match(r"defaults/preferences/.+\.js", filename))
def tests(self):
for ref, bug in self.MARIONETTE_REFERENCES.items():
yield self.get_test(
bug,
ref,
"Marionette references are not allowed as it could lead to"
"the browser not being secure. Please remove them.")
for ref, bug in self.MARIONETTE_PREFS.items():
yield self.get_test(
bug,
ref,
"Marionette preferences are not allowed as it could lead to"
"the browser not being secure. Please remove them.")
@register_generator
class PasswordsInPrefsRegexTests(RegexTestGenerator):
"""
These regex tests will ensure that the developer is not storing passwords
in the `/defaults/preferences` JS files.
Added from bug 647109
"""
@classmethod
def applicable(cls, err, filename, document):
return bool(re.match(r"defaults/preferences/.+\.js", filename))
def js_tests(self):
yield self.get_test(
"password",
"Passwords may be stored in `defaults/preferences/*.js`",
"Storing passwords in the preferences JavaScript files is "
"insecure. The Login Manager should be used insted.")
@register_generator
class BannedPrefRegexTests(RegexTestGenerator):
"""
These regex tests will find whether banned preference branches are being
referenced from outside preference JS files.
Added from bug 676815
"""
@classmethod
def applicable(cls, err, filename, document):
return not filename.startswith("defaults/preferences/")
def tests(self):
from javascript.predefinedentities import (BANNED_PREF_BRANCHES,
BANNED_PREF_REGEXPS)
for pattern in BANNED_PREF_REGEXPS:
yield self.get_test(
r"[\"']" + pattern,
"Potentially unsafe preference branch referenced",
"Extensions should not alter preferences matching /%s/."
% pattern)
for branch in BANNED_PREF_BRANCHES:
yield self.get_test(
branch.replace(r".", r"\."),
"Potentially unsafe preference branch referenced",
"Extensions should not alter preferences in the `%s` "
"preference branch" % branch)
@register_generator
class ChromePatternRegexTests(RegexTestGenerator):
"""
Test that an Add-on SDK (Jetpack) add-on doesn't use interfaces that are
not part of the SDK.
Added from bugs 689340, 731109
"""
def tests(self):
# We want to re-wrap the test because if it detects something, we're
# going to set the `requires_chrome` metadata value to `True`.
def rewrap():
wrapper = self.get_test(
r"(?<![\'\"])require\s*\(\s*[\'\"]"
r"(chrome|window-utils|observer-service)[\'\"]\s*\)",
"Usage of non-SDK interface",
"This SDK-based add-on uses interfaces that aren't part "
"of the SDK.")
if wrapper():
self.err.metadata["requires_chrome"] = True
yield rewrap
@register_generator
class JSPrototypeExtRegexTests(RegexTestGenerator):
"""
These regex tests will ensure that the developer is not modifying the
prototypes of the global JS types.
Added from bug 696172
"""
@classmethod
def applicable(cls, err, filename, document):
return not (filename.endswith(".jsm") or "EXPORTED_SYMBOLS" in document)
def js_tests(self):
yield self.get_test(
r"(String|Object|Number|Date|RegExp|Function|Boolean|Array|"
r"Iterator)\.prototype(\.[a-zA-Z0-9]+|\[.+\]) =",
"JS prototype extension",
"It appears that an extension of a built-in JS type was made. "
"This is not allowed for security and compatibility reasons.",
flags=re.I)
class CompatRegexTestHelper(RegexTestGenerator):
"""
A helper that makes it easier to stay DRY. This will automatically check
for applicability against the value set as the app_versions_fallback.
"""
def __init__(self, *args, **kwargs):
super(CompatRegexTestHelper, self).__init__(*args, **kwargs)
self.app_versions_fallback = self.VERSION
@classmethod
def applicable(cls, err, filename, document):
return err.supports_version(cls.VERSION)
DEP_INTERFACE = "Deprecated interface in use"
DEP_INTERFACE_DESC = ("This add-on uses `%s`, which is deprecated in Gecko %d "
"and should not be used.")
@register_generator
class Gecko5RegexTests(CompatRegexTestHelper):
"""Regex tests for Gecko 5 updates."""
VERSION = FX5_DEFINITION
def tests(self):
yield self.get_test(
r"navigator\.language",
"`navigator.language` may not behave as expected.",
"JavaScript code was found that references `navigator."
"language`, which will no longer indicate that language of "
"the application's UI. To maintain existing functionality, "
"`general.useragent.locale` should be used in place of "
"`navigator.language`.", compat_type="error",
log_function=self.err.notice)
@register_generator
class Gecko6RegexTests(CompatRegexTestHelper):
"""Regex tests for Gecko 6 updates."""
VERSION = FX6_DEFINITION
def tests(self):
interfaces = {"nsIDOMDocumentTraversal": 655514,
"nsIDOMDocumentRange": 655513,
"IWeaveCrypto": 651596}
for interface, bug in interfaces.items():
yield self.get_test_bug(
bug=bug,
pattern=interface,
title=DEP_INTERFACE,
message=DEP_INTERFACE_DESC % (interface, 6),
compat_type="error")
yield self.get_test_bug(
614181, r"app\.update\.timer",
"`app.update.timer` is incompatible with Gecko 6",
"The `app.update.timer` preference is being replaced by the "
"`app.update.timerMinimumDelay` preference in Gecko 6.",
compat_type="error")
@register_generator
class Gecko7RegexTests(CompatRegexTestHelper):
"""Regex tests for Gecko 7 updates."""
VERSION = FX7_DEFINITION
def tests(self):
interfaces = {"nsIDOMDocumentStyle": 658904,
"nsIDOMNSDocument": 658906,
"nsIDOM3TypeInfo": 660539,
"nsIDOM3Node": 659053}
for interface, bug in interfaces.items():
yield self.get_test_bug(
bug=bug,
pattern=interface,
title=DEP_INTERFACE,
message=DEP_INTERFACE_DESC % (interface, 7),
compat_type="error")
yield self.get_test_bug(
633266, "nsINavHistoryObserver",
"`nsINavHistoryObserver` interface has changed in Gecko 7",
"The `nsINavHistoryObserver` interface has change in Gecko 7. "
"Most function calls now require a GUID parameter. Please "
"refer to %s for more information." % NSINHS_LINK,
compat_type="error", log_function=self.err.notice)
yield self.get_test_bug(
617539, "nsIMarkupDocumentViewer_MOZILLA_2_0_BRANCH",
"`_MOZILLA_2_0_BRANCH` has been merged in Gecko 7",
"The `_MOZILLA_2_0_BRANCH` interfaces have been merged out. "
"You should now use the namespace without the "
"`_MOZILLA_2_0_BRANCH` suffix.", compat_type="warning")
@register_generator
class Gecko8RegexTests(CompatRegexTestHelper):
"""Regex tests for Gecko 8 updates."""
VERSION = FX8_DEFINITION
def tests(self):
interfaces = {"nsISelection2": 672536,
"nsISelection3": 672536}
for interface, bug in interfaces.items():
yield self.get_test_bug(
bug=bug,
pattern=interface,
title=DEP_INTERFACE,
message=DEP_INTERFACE_DESC % (interface, 8),
compat_type="error")
NSIDWI_MDN = ("https://developer.mozilla.org/en/"
"XPCOM_Interface_Reference/nsIDOMWindow")
yield self.get_test(
"nsIDOMWindowInternal", DEP_INTERFACE,
"The `nsIDOMWindowInternal` interface has been deprecated in "
"Gecko 8. You can use the `nsIDOMWindow` interface instead. "
"See %s for more information." % NSIDWI_MDN,
compat_type="warning")
ISO8601_MDC = ("https://developer.mozilla.org/en/JavaScript/Reference/"
"Global_Objects/Date")
yield self.get_test(
"ISO8601DateUtils",
"`ISO8601DateUtils.jsm` was removed in Gecko 8",
"The `ISO8601DateUtils object is no longer available in Gecko "
"8. You can use the normal `Date` object instead. See %s"
"for more information." % ISO8601_MDC,
compat_type="error")
@register_generator
class Gecko9RegexTests(CompatRegexTestHelper):
"""Regex tests for Gecko 8 updates."""
VERSION = FX9_DEFINITION
def tests(self):
yield self.get_test_bug(
679971, r"navigator\.taintEnabled",
"`navigator.taintEnabled` was removed in Gecko 9",
"The `taintEnabled` function is no longer available in Gecko "
"9. Since this function was only used for browser detection "
"and this doesn't belong in extension code, it should be "
"removed if possible.", compat_type="warning")
chrome_context_props = [r"\.nodePrincipal", r"\.documentURIObject",
r"\.baseURIObject", ]
for property in chrome_context_props:
yield self.get_test_bug(
660233, property,
"`%s` only available in chrome contexts" % property,
"The `%s` property is no longer accessible from untrusted "
"scripts as of Gecko 9." % property,
compat_type="warning", log_function=self.err.notice)
yield self.get_test_bug(
568971, r"nsIGlobalHistory3", DEP_INTERFACE,
DEP_INTERFACE_DESC % ("nsIGlobalHistory3", 9),
compat_type="warning")
# geo.wifi.* warnings
for pattern in ["geo.wifi.uri", r"geo.wifi.protocol", ]:
yield self.get_test_bug(
689252, pattern.replace(".", r"\."),
"`%s` removed in Gecko 9" % pattern,
"The `geo.wifi.*` preferences are no longer created by "
"default in Gecko 9. Reading them without testing for "
"their presence can result in unexpected errors.",
compat_type="error")
@register_generator
class Gecko11RegexTests(CompatRegexTestHelper):
"""Regex tests for Gecko 11 updates."""
VERSION = FX11_DEFINITION
def tests(self):
yield self.get_test_bug(
700490, "nsICharsetResolver", DEP_INTERFACE,
DEP_INTERFACE_DESC % ("nsICharsetResolver", 11),
compat_type="error")
yield self.get_test_bug(
701875, r"omni\.jar",
"`omni.jar` renamed to `omni.ja` in Gecko 11",
"This add-on references `omni.jar`, which was renamed to "
"`omni.ja`. You should avoid referencing this file directly, "
"and at least update this reference for any versions that "
"support Gecko 11 and above.", compat_type="error")
@register_generator
class Gecko12RegexTests(CompatRegexTestHelper):
"""Regex tests for Gecko 12 updates."""
VERSION = FX12_DEFINITION
def tests(self):
yield self.get_test_bug(
675221, "nsIProxyObjectManager", DEP_INTERFACE,
"This add-on uses nsIProxyObjectManager, which was removed in "
"Gecko 12.", compat_type="error")
yield self.get_test_bug(
713825, "documentCharsetInfo",
"Deprecated JavaScript property",
"documentCharsetInfo has been deprecated in Gecko 12 and "
"should no longer be used.", compat_type="error")
yield self.get_test_bug(
711838, "nsIJetpack(Service)?", DEP_INTERFACE,
"This add-on uses the Jetpack service, which was deprecated "
"long ago and is no longer included in Gecko 12. Please "
"update your add-on to use a more recent version of the "
"Add-ons SDK.", compat_type="error")
# `chromemargin`; bug 735876
yield self.get_test_bug(
735876, "chromemargin",
"`chromemargin` attribute changed in Gecko 12",
"This add-on uses the chromemargin attribute, which after "
"Gecko 12 will not work in the same way with values other "
"than 0 or -1.", compat_type="error",
log_function=self.err.notice)
@register_generator
class Gecko13RegexTests(CompatRegexTestHelper):
"""Regex tests for Gecko 13 updates."""
VERSION = FX13_DEFINITION
def tests(self):
yield self.get_test_bug(
613588, "nsILivemarkService", DEP_INTERFACE,
"This add-on uses nsILivemarkService, which has been "
"deprecated in Gecko 13. Some of its functions may not work "
"as expected. mozIAsyncLivemarks should be used instead.",
compat_type="error")
yield self.get_test_bug(
718255, "nsIPrefBranch2", DEP_INTERFACE,
"This add-on uses nsIPrefBranch2, which has been merged into "
"nsIPrefBranch in Gecko 13. Once you drop support for old "
"versions of Gecko, you should stop using nsIPrefBranch2.",
compat_type="warning")
yield self.get_test_bug(
650784, "nsIScriptableUnescapeHTML", DEP_INTERFACE,
"This add-on uses nsIScriptableUnescapeHTML, which has been "
"deprecated in Gecko 13 in favor of the nsIParserUtils "
"interface. While it will continue to work for the foreseeable "
"future, it is recommended that you change your code to use "
"nsIParserUtils as soon as possible.",
compat_type="warning", log_function=self.err.notice)
yield self.get_test_bug(
672507, "nsIAccessNode", DEP_INTERFACE,
"The `nsIAccessNode` interface has been merged into "
"`nsIAccessible`. You should use that interface instead.",
compat_type="error")
GLOBALSTORAGE_URL = ("https://developer.mozilla.org/en/XUL_School/"
"Local_Storage")
yield self.get_test_bug(
687579, "globalStorage",
"`globalStorage` removed in Gecko 13",
"As of Gecko 13, the `globalStorage` object has been removed. "
"See %s for alternatives." % GLOBALSTORAGE_URL,
compat_type="error")
yield self.get_test_bug(
702639, "excludeItemsIfParentHasAnnotation",
"`excludeItemsIfParentHasAnnotation` no longer supported",
"The `excludeItemsIfParentHasAnnotation` query option is no "
"longer supported, as of Gecko 13.", compat_type="error")
@register_generator
class Gecko14RegexTests(CompatRegexTestHelper):
"""Regex tests for Gecko 14 updates."""
VERSION = FX14_DEFINITION
def tests(self):
BLOB_BUILDER_DEP = "`BlobBuilder` and `MozBlobBuilder` are deprecated."
yield self.get_test_bug(
736687, "(Moz)?BlobBuilder", BLOB_BUILDER_DEP,
"The `BlobBuilder` and `MozBlobBuilder` objects are now "
"deprecated. You should use the `Blob` constructor instead.",
compat_type="warning")
yield self.get_test_bug(
682360, "nsILocalFile",
"`nsILocalFile` should be replaced with `nsIFile`.",
"Starting with Gecko 14, `nsILocalFile` inherits all functions "
"and attributes from `nsIFile`, meaning that you no longer "
"need to use `nsILocalFile`. If your add-on doesn't support "
"versions older than 14, you should use `nsIFile` instead of "
"`nsILocalFile`.", compat_type="warning")
yield self.get_test_bug(
737133, "onFaviconDataAvailable",
"`onFaviconDataAvailable` renamed to `onComplete`.",
"The `onFaviconDataAvailable` function has been renamed to "
"`onComplete`. Also note that the function behaves slightly "
"differently now.", compat_type="error")
GUID_LINK = ("http://blog.bonardo.net/2012/02/16/"
"add-ons-devs-heads-up-we-are-killing-old-bookmarks-guids")
yield self.get_test(
"(getItemGUID|setItemGUID|getItemIdForGUID)",
"`getItemGUID`, `setItemGUID`, and `getItemIdForGUID` were "
"removed.",
"Item GUIDs have been dropped from the Bookmarks Service. See "
"%s for more information." % GUID_LINK, compat_type="error")
yield self.get_test_bug(
737841, "redirectsMode",
"`redirectsMode` removed from `nsINavHistoryQueryOptions`",
"The `redirectsMode` option has been removed from the "
"`nsINavHistoryQueryOptions` interface. Error visits are no "
"longer stored in the history, so it is no longer necessary.",
compat_type="error")
@register_generator
class Gecko15RegexTests(CompatRegexTestHelper):
"""Regex tests for Gecko 15 updates."""
VERSION = FX15_DEFINITION
def tests(self):
yield self.get_test_bug(
615213, "nsIGlobalHistory",
"`nsIGlobalHistory` has been removed.",
"The `nsIGlobalHistory` interface has been removed. You can "
"use `nsIGlobalHistory2` instead.", compat_type="error")
nISSWLink = ("https://blog.mozilla.org/nfroyd/2012/05/14/"
"statement-wrappers-have-been-deprecated/")
yield self.get_test(
"mozIStorageStatementWrapper",
"`mozIStorageStatementWrapper` has been removed.",
"The `mozIStorageStatementWrapper` interface has been removed. "
"It is no longer necessary, you can use `mozIStorageStatement` "
"directly instead. See %s for more information." % nISSWLink,
compat_type="error")
aPWDLink = ("https://developer.mozilla.org/en-US/docs/"
"XPCOM_Interface_Reference/nsIBrowserHistory"
"#addPageWithDetails%28%29")
yield self.get_test(
"addPageWithDetails",
"`addPageWithDetails` has been removed.",
"The `addPageWithDetails` function has been removed. You can "
"use the equivalent `mozIAsyncHistory.updatePlaces` function "
"instead. See %s for more information." % aPWDLink,
compat_type="error")
yield self.get_test_bug(
730340, "(_DOMElement|_feedURI|_siteURI|_cellProperties)",
"Private Properties removed from Places code.",
"Places nodes no longer hold metadata in private properties. "
"If you're using these properties to obtain Places data, this "
"will no longer work.", compat_type="error")
@register_generator
class Gecko16RegexTests(CompatRegexTestHelper):
"""Regex tests for Gecko 16 updates."""
VERSION = FX16_DEFINITION
def tests(self):
yield self.get_test(
"nsITransferable",
"`nsITransferable` has been changed in Gecko 16.",
"The `nsITransferable` interface has changed to better "
"support Private Browsing Mode. After instantiating the "
"object, you should call the `init` function on it before "
"any other functions are called. See %s for more "
"information." % NSIT_LINK,
compat_type="error")
yield self.get_test_bug(
726378, "mozIndexedDB",
"`mozIndexedDB` has been unprefixed in Gecko 16.",
"The `mozIndexedDB` object has been renamed to `indexedDB` in "
"Firefox 16.", compat_type="error")
def js_tests(self):
yield self.get_test(
"Moz(Transition|Animation|Transform)[a-zA-Z]+",
"Some CSS selectors have been unprefixed in Gecko 16.",
UNPREFIXED_MESSAGE, compat_type="warning")
@register_generator
class Gecko17RegexTests(CompatRegexTestHelper):
"""Regex tests for Gecko 17 updates."""
VERSION = FX17_DEFINITION
CFMM_URL = ("http://mxr.mozilla.org/mozilla-beta/source/content/base/"
"public/nsIMessageManager.idl")
def js_tests(self):
yield self.get_test_bug(
776825, "nsIChromeFrameMessageManager",
"`nsIChromeFrameMessageManager` has been removed.",
"The `nsIChromeFrameMessageManager` interface has been "
"removed, and the new Message Manager interfaces should be "
"used instead. See %s for more information." % self.CFMM_URL,
compat_type="error")
yield self.get_test_bug(
761278, "onuploadprogress",
"`onuploadprogress` has been removed.",
"The `onuploadprogress` property has been removed from "
"`XMLHttpRequest`.", compat_type="error")
yield self.get_test_bug(
327244, "checkLoadURI(Str)?",
"`checkLoadURI` and `checkLoadURIStr` have been removed.",
"The `checkLoadURI` and `checkLoadURIStr` interfaces have "
"been removed. You should use `checkLoadURIWithPrincipal` "
"instead.", compat_type="error")
@register_generator
class Gecko18RegexTests(CompatRegexTestHelper):
"""Regex tests for Gecko 18 updates."""
VERSION = FX18_DEFINITION
BLOB_URL = "https://developer.mozilla.org/en-US/docs/DOM/BlobBuilder"
IMG_URL = ("https://developer.mozilla.org/en-US/docs/"
"XPCOM_Interface_Reference/imgICache")
def js_tests(self):
yield self.get_test_bug(
794602, "saveURI",
"`saveURI` has been changed.",
"The `saveURI` function have changed to support per-window "
"private browsing. You should now pass a context as an "
"additional argument.",
compat_type="error", log_function=self.err.notice)
yield self.get_test_bug(
769764,
"nsIProtocolProxyService|nsIProxyAutoConfig|newProxiedChannel",
"Proxy interfaces have been changed.",
"The `nsIProtocolProxyService` and `nsIProxyAutoConfig` "
"interfaces, as well as the `newProxiedChannel` function have "
"changed in order to make the proxy API asynchronous.",
compat_type="error", log_function=self.err.notice)
yield self.get_test_bug(
722861, "imgI(Cache|Loader)",
"`imgICache` and `imgILoader` have been deprecated.",
"The `imgICache` and `imgILoader` interfaces have been "
"deprecated in Gecko 18. You should use `imgITools` instead. "
"See %s for more information." % self.IMG_URL,
compat_type="error")
yield self.get_test_bug(
774963, "removeDataFromDomain",
"`removeDataFromDomain` has been moved.",
"The `removeDataFromDomain` function has been moved to "
"`ClearRecentHistory.jsm`.",
compat_type="error", log_function=self.err.notice)
yield self.get_test_bug(
695399, "openCacheEntry",
"`openCacheEntry` no longer works from main thread.",
"The `openCacheEntry` function no longer works when invoked "
"from the main thread. You should use `asyncOpenCacheEntry` "
"instead.",
compat_type="error", log_function=self.err.notice)
yield self.get_test_bug(
744907, "BlobBuilder",
"`BlobBuiler` has been removed.",
"The `BlobBuilder` object has been removed. You should use "
"the `Blob` constructor instead. See %s for more "
"information." % self.BLOB_URL,
compat_type="error")
yield self.get_test_bug(
741059, "setAndLoadFaviconForPage",
"`setAndLoadFaviconForPage` has been changed.",
"The `setAndLoadFaviconForPage` function have changed to "
"support per-window private browsing. You should now pass a "
"load type as an additional argument.",
compat_type="error", log_function=self.err.notice)
yield self.get_test_bug(
795065, "addDownload|saveURL",
"`addDownlod` and `saveURL` have been changed.",
"The `addDownload` and `saveURL` functions have changed to "
"support per-window private browsing. You should now pass an "
"additional argument to them.",
compat_type="error", log_function=self.err.notice)
@register_generator
class Gecko19RegexTests(CompatRegexTestHelper):
"""Regex tests for Gecko 19 updates."""
VERSION = FX19_DEFINITION
def js_tests(self):
yield self.get_test_bug(
723002, "nsIContentPrefService",
"`nsIContentPrefService` has been changed.",
"`nsIContentPrefService` has been changed to support "
"per-window private browsing. Most of its functions now "
"require an additional argument to specify a context.",
compat_type="error", log_function=self.err.notice)
yield self.get_test_bug(
664695, "getMessageArray",
"`nsIConsoleService::getMessageArray` has been changed.",
"The `getMessageArray` function has changed, and now it returns "
"the array instead of setting the object passed as a parameter.",
compat_type="error", log_function=self.err.notice)
@register_generator
class Gecko20RegexTests(CompatRegexTestHelper):
"""Regex tests for Gecko 20 updates."""
VERSION = FX20_DEFINITION
PRIVATE_BROWSING_LINK = "https://developer.mozilla.org/en-US/docs/Updating_addons_broken_by_private_browsing_changes"
DECODE_LINK = "https://bugzilla.mozilla.org/show_bug.cgi?id=816362"
EDITABLE_LINK = "https://bugzilla.mozilla.org/show_bug.cgi?id=827546"
PROFILE_LINK = "https://bugzilla.mozilla.org/show_bug.cgi?id=807757"
PLACES_IMPORT_LINK = "https://bugzilla.mozilla.org/show_bug.cgi?id=763295"
def js_tests(self):
for pbs in ("nsIPrivateBrowsingService", "private-browsing"):
yield self.get_test_bug(
826079, pbs,
"`nsIPrivateBrowsingService` has been removed.",
"`nsIPrivateBrowsingService` and its related observer "
"notifications have been removed due to the new per-window "
"private browsing mode. See {0} for more "
"information.".format(self.PRIVATE_BROWSING_LINK),
compat_type="error", log_function=self.err.notice)
yield self.get_test_bug(
816362, "decodeImageData",
"`decodeImageData` has been deprecated.",
"decodeImageData has been deprecated. You should instead use "
"decodeImage, from the same interface. See {0} for more "
"information.".format(self.DECODE_LINK),
compat_type="warning", log_function=self.err.notice)
yield self.get_test_bug(
827546, "nsIDOMNSEditableElement",
"In Firefox 20, using `QueryInterface` of a non-editable element "
"to `nsIDOMNSEditableElement` doesn't throw an exception as "
"expected.",
"In Firefox 20, using `QueryInterface` of a non-editable element "
"to `nsIDOMNSEditableElement` doesn't throw an exception as "
"expected. This has been fixed in Firefox 21. Using `instanceof` "
"is the recommended way of doing this, which avoids this error. "
"See {0} for more information.'".format(self.EDITABLE_LINK),
compat_type="warning", log_function=self.err.notice)
yield self.get_test_bug(
807757, "nsIProfile",
"`nsIProfile` and `nsIProfileChangeStatus` have been removed.",
"`nsIProfile` and `nsIProfileChangeStatus` have been removed "
"because they weren't in use anymore. See {0} for more "
"information.".format(self.PROFILE_LINK),
compat_type="error", log_function=self.err.notice)
yield self.get_test_bug(
763295, "nsIPlacesImportExportService",
"`nsIProfile` and `nsIProfileChangeStatus` have been removed.",
"`nsIPlacesImportExportService`` was removed. You can use "
"`BookmarkHTMLUtils.jsm` "
"(resource://gre/modules/BookmarkHTMLUtils.jsm) instead. See {0} "
"for more information.".format(self.PLACES_IMPORT_LINK),
compat_type="error", log_function=self.err.notice)
@register_generator
class Gecko21RegexTests(CompatRegexTestHelper):
"""Regex tests for Gecko 21 updates."""
VERSION = FX21_DEFINITION
def js_tests(self):
for pattern in (
"resource:///modules/.*",
r"resource://gre/modules/(HUDService|MigrationUtils|"
"PlacesUIUtils|PropertyPanel|RecentWindow|offlineAppCache|"
"source-editor)\.jsm"):
yield self.get_test_bug(
763295, pattern,
"Some JS Modules were moved to a different location.",
"Some JS modules were moved from `resource:///` and "
"`resource://gre/` to `resource://app/`.",
compat_type="error", log_function=self.err.warning)
yield self.get_test_bug(
835543, "(RESULT_TYPE_DYNAMIC_CONTAINER|RESULT_TYPE_FULL_VISIT)",
"`nsINavHistoryService` members removed.",
"`RESULT_TYPE_DYNAMIC_CONTAINER` and `RESULT_TYPE_FULL_VISIT` "
"were removed.",
compat_type="error", log_function=self.err.warning)
yield self.get_test_bug(
826409, "(onBeforeDeleteURI|onBeforeItemRemoved)",
"Event handlers removed in Gecko 21",
"`onBeforeDeleteURI` and `onBeforeItemRemoved` were removed.",
compat_type="error", log_function=self.err.warning)
@register_generator
class Thunderbird7RegexTests(CompatRegexTestHelper):
"""Regex tests for the Thunderbird 7 update."""
VERSION = TB7_DEFINITION
def tests(self):
yield self.get_test_bug(
621213, r"resource:///modules/dictUtils.js",
"`dictUtils.js` was removed in Thunderbird 7",
"The `dictUtils.js` file is no longer available in "
"Thunderbird as of version 7. You can use `Dict.jsm` "
"instead.", compat_type="error")
ab_patterns = [r"rdf:addressdirectory",
r"GetResource\(.*?\)\s*\.\s*"
r"QueryInterface\(.*?nsIAbDirectory\)",]
for pattern in ab_patterns:
yield self.get_test_bug(
621213, pattern,
"The address book does not use RDF in Thunderbird 7",