Bug 1143879 - Implement lang member of Web manifest. r=ehsan.
authorMarcos Caceres <marcos@marcosc.com>
Mon, 25 May 2015 16:35:33 -0400
changeset 245503 a96e3936c2cb36717119dcc2203cff3ef77661b5
parent 245502 4362d9251296e0d7269c5855522bb6c4c696b68f
child 245504 66896f9c0ebd5560ef8f76913ca578b23e9f922b
push id60196
push usermcaceres@mozilla.com
push dateMon, 25 May 2015 21:02:11 +0000
treeherdermozilla-inbound@a96e3936c2cb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs1143879, 100644
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1143879 - Implement lang member of Web manifest. r=ehsan. --- dom/manifest/ManifestProcessor.jsm | 24 ++++- dom/manifest/test/mochitest.ini | 4 +- dom/manifest/test/test_ManifestProcessor_lang.html | 112 +++++++++++++++++++++ 3 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 dom/manifest/test/test_ManifestProcessor_lang.html
dom/manifest/ManifestProcessor.jsm
dom/manifest/test/mochitest.ini
dom/manifest/test/test_ManifestProcessor_lang.html
--- a/dom/manifest/ManifestProcessor.jsm
+++ b/dom/manifest/ManifestProcessor.jsm
@@ -16,17 +16,17 @@
  * icons and splash_screens.
  *
  * TODO: The constructor should accept the UA's supported orientations.
  * TODO: The constructor should accept the UA's supported display modes.
  * TODO: hook up developer tools to console. (1086997).
  */
 /*exported EXPORTED_SYMBOLS */
 /*JSLint options in comment below: */
-/*globals Components, XPCOMUtils*/
+/*globals Components, XPCOMUtils, Intl*/
 'use strict';
 this.EXPORTED_SYMBOLS = ['ManifestProcessor']; // jshint ignore:line
 const imports = {};
 const {
   utils: Cu
 } = Components;
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 Cu.importGlobalProperties(['URL']);
@@ -95,16 +95,17 @@ ManifestProcessor.prototype = {
     if (typeof rawManifest !== 'object' || rawManifest === null) {
       let msg = 'Manifest needs to be an object.';
       console.warn(msg);
       rawManifest = {};
     }
     const extractor = new ManifestValueExtractor(console);
     const imgObjProcessor = new ImgObjProcessor(console, extractor);
     const processedManifest = {
+      'lang': processLangMember(rawManifest),
       'start_url': processStartURLMember(rawManifest, manifestURL, docURL),
       'display': processDisplayMember(rawManifest),
       'orientation': processOrientationMember(rawManifest),
       'name': processNameMember(rawManifest),
       'icons': imgObjProcessor.process(
         rawManifest, manifestURL, 'icons'
       ),
       'splash_screens': imgObjProcessor.process(
@@ -241,12 +242,31 @@ ManifestProcessor.prototype = {
         objectName: 'manifest',
         object: aManifest,
         property: 'theme_color',
         expectedType: 'string',
         trim: true
       };
       return extractor.extractColorValue(spec);
     }
+
+    function processLangMember(aManifest) {
+      const spec = {
+        objectName: 'manifest',
+        object: aManifest,
+        property: 'lang',
+        expectedType: 'string',
+        trim: true
+      };
+      let tag = extractor.extractValue(spec);
+      // TODO: Check if tag is structurally valid.
+      //       Cannot do this because we don't support Intl API on Android.
+      //       https://bugzilla.mozilla.org/show_bug.cgi?id=864843
+      //       https://github.com/tc39/ecma402/issues/5
+      // TODO: perform canonicalization on the tag.
+      //       Can't do this today because there is no direct means to
+      //       access canonicalization algorithms through Intl API.
+      //       https://github.com/tc39/ecma402/issues/5
+      return tag;
+    }
   }
 };
-
 this.ManifestProcessor = ManifestProcessor; // jshint ignore:line
--- a/dom/manifest/test/mochitest.ini
+++ b/dom/manifest/test/mochitest.ini
@@ -1,19 +1,19 @@
 [DEFAULT]
 support-files =
 	common.js
 	resource.sjs
 	manifestLoader.html
-
 [test_ImageObjectProcessor_background_color.html]
 [test_ImageObjectProcessor_density.html]
 [test_ImageObjectProcessor_sizes.html]
 [test_ImageObjectProcessor_src.html]
 [test_ImageObjectProcessor_type.html]
 [test_ManifestProcessor_display.html]
 [test_ManifestProcessor_icons.html]
 [test_ManifestProcessor_JSON.html]
+[test_ManifestProcessor_lang.html]
 [test_ManifestProcessor_name_and_short_name.html]
 [test_ManifestProcessor_orientation.html]
-[test_ManifestProcessor_start_url.html]
 [test_ManifestProcessor_scope.html]
 [test_ManifestProcessor_splash_screens.html]
+[test_ManifestProcessor_start_url.html]
new file mode 100644
--- /dev/null
+++ b/dom/manifest/test/test_ManifestProcessor_lang.html
@@ -0,0 +1,112 @@
+<!DOCTYPE HTML>
+<!--
+Bug 1143879 - Implement lang member of Web manifest
+https://bugzilla.mozilla.org/show_bug.cgi?id=1143879
+-->
+<meta charset="utf-8">
+<title>Test for Bug 1143879 - Implement lang member of Web manifest</title>
+<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+<script src="common.js"></script>
+<script>
+/**
+ * lang member
+ * https://w3c.github.io/manifest/#lang-member
+ **/
+/*globals is, typeTests, data, processor, seperators, lineTerminators, todo_is*/
+'use strict';
+// Type checks: checks that only strings are accepted.
+for (var type of typeTests) {
+  var expected = `Expect non-string to be undefined.`;
+  data.jsonText = JSON.stringify({
+    lang: type
+  });
+  var result = processor.process(data);
+  is(result.lang, undefined, expected);
+}
+
+// Test valid language tags - derived from IANA and BCP-47 spec
+// and our Intl.js implementation.
+var validTags = [
+  'aa', 'ab', 'ae', 'af', 'ak', 'am', 'an', 'ar', 'as', 'av', 'ay', 'az',
+  'ba', 'be', 'bg', 'bh', 'bi', 'bm', 'bn', 'bo', 'br', 'bs', 'ca', 'ce',
+  'ch', 'co', 'cr', 'cs', 'cu', 'cv', 'cy', 'da', 'de', 'dv', 'dz', 'ee',
+  'el', 'en', 'eo', 'es', 'et', 'eu', 'fa', 'ff', 'fi', 'fj', 'fo', 'fr',
+  'fy', 'ga', 'gd', 'gl', 'gn', 'gu', 'gv', 'ha', 'he', 'hi', 'ho', 'hr',
+  'ht', 'hu', 'hy', 'hz', 'ia', 'id', 'ie', 'ig', 'ik', 'in', 'io',
+  'is', 'it', 'iu', 'iw', 'ja', 'ji', 'jv', 'jw', 'ka', 'kg', 'ki', 'kj',
+  'kk', 'kl', 'km', 'kn', 'ko', 'kr', 'ks', 'ku', 'kv', 'kw', 'ky', 'la',
+  'lb', 'lg', 'li', 'ln', 'lo', 'lt', 'lu', 'lv', 'mg', 'mh', 'mi', 'mk',
+  'ml', 'mn', 'mo', 'mr', 'ms', 'mt', 'my', 'na', 'nb', 'nd', 'ne', 'ng',
+  'nl', 'nn', 'no', 'nr', 'nv', 'ny', 'oc', 'oj', 'om', 'or', 'os', 'pa',
+  'pi', 'pl', 'ps', 'pt', 'qu', 'rm', 'rn', 'ro', 'ru', 'rw', 'sa', 'sc',
+  'sd', 'se', 'sg', 'sh', 'si', 'sk', 'sl', 'sm', 'sn', 'so', 'sq', 'sr',
+  'ss', 'st', 'su', 'sv', 'sw', 'ta', 'te', 'tg', 'th', 'ti', 'tk', 'tl',
+  'tn', 'to', 'tr', 'ts', 'tt', 'tw', 'ty', 'ug', 'uk', 'ur', 'uz', 've',
+  'vi', 'vo', 'wa', 'wo', 'xh', 'yi', 'yo', 'za', 'zh', 'zu', 'en-US',
+  'jp-JS', 'pt-PT', 'pt-BR', 'de-CH', 'de-DE-1901', 'es-419', 'sl-IT-nedis',
+  'en-US-boont', 'mn-Cyrl-MN', 'x-fr-CH', 'sr-Cyrl', 'sr-Latn',
+  'hy-Latn-IT-arevela', 'zh-TW', 'en-GB-boont-r-extended-sequence-x-private',
+  'zh-nan-hans-bu-variant2-variant1-u-ca-chinese-t-zh-latn-x-private',
+  'zh-cmn-Hans-CN', 'cmn-Hans-CN', 'zh-yue-HK', 'yue-HK',
+  'de-CH-x-phonebk', 'az-Arab-x-AZE-derbend', 'x-whatever',
+  'qaa-Qaaa-QM-x-southern'
+];
+for (var tag of validTags) {
+  var expected = `Expect lang to be ${tag}.`;
+  data.jsonText = JSON.stringify({
+    lang: tag
+  });
+  var result = processor.process(data);
+  is(result.lang, tag, expected);
+}
+
+// trim tests - check that language tags get trimmed properly.
+for (var tag of validTags) {
+  var expected = `Expect trimmed tag to be returned.`;
+  var expandedtag = seperators + lineTerminators + tag;
+  expandedtag += lineTerminators + seperators;
+  data.jsonText = JSON.stringify({
+    lang: expandedtag
+  });
+  var result = processor.process(data);
+  is(result.lang, tag, expected);
+}
+
+//Invalid language tags, derived from BCP-47 and made up.
+var invalidTags = [
+  'de-419-DE', ' a-DE ', 'ar-a-aaa-b-bbb-a-ccc', 'sdafsdfaadsfdsf', 'i',
+  'i-phone', 'en US', 'EN-*-US-JP', 'JA-INVALID-TAG', '123123123'
+];
+for (var item of invalidTags) {
+  var expected = `Expect invalid tag (${item}) to be treated as undefined.`;
+  data.jsonText = JSON.stringify({
+    lang: item
+  });
+  var result = processor.process(data);
+  todo_is(result.lang, undefined, expected);
+}
+
+// Canonical form conversion tests. We convert the following tags, which are in
+// canonical form, to upper case and expect the processor to return them
+// in canonical form.
+var canonicalTags = [
+  'jp-JS', 'pt-PT', 'pt-BR', 'de-CH', 'de-DE-1901', 'es-419', 'sl-IT-nedis',
+  'en-US-boont', 'mn-Cyrl-MN', 'x-fr-CH', 'sr-Cyrl', 'sr-Latn',
+  'hy-Latn-IT-arevela', 'zh-TW', 'en-GB-boont-r-extended-sequence-x-private',
+  'zh-cmn-Hans-CN', 'cmn-Hans-CN', 'zh-yue-HK', 'yue-HK',
+  'de-CH-x-phonebk', 'az-Arab-x-AZE-derbend', 'x-whatever',
+  'qaa-Qaaa-QM-x-southern'
+];
+
+for (var tag of canonicalTags) {
+  var uppedTag = tag.toUpperCase();
+  var expected = `Expect tag (${uppedTag}) to be in canonical form (${tag}).`;
+  data.jsonText = JSON.stringify({
+    lang: uppedTag
+  });
+  var result = processor.process(data);
+  todo_is(result.lang, tag, expected);
+}
+
+</script>