View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host;
16  
17  import org.htmlunit.WebDriverTestCase;
18  import org.htmlunit.junit.BrowserRunner;
19  import org.htmlunit.junit.annotation.Alerts;
20  import org.junit.Test;
21  import org.junit.runner.RunWith;
22  
23  /**
24   * Tests for {@link Navigator}.
25   *
26   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
27   * @author Daniel Gredler
28   * @author Marc Guillemot
29   * @author Ahmed Ashour
30   * @author Frank Danek
31   * @author Ronald Brill
32   */
33  @RunWith(BrowserRunner.class)
34  public class NavigatorTest extends WebDriverTestCase {
35  
36      /**
37       * Tests the {@code appCodeName} property.
38       * @throws Exception on test failure
39       */
40      @Test
41      public void appCodeName() throws Exception {
42          attribute("appCodeName", getBrowserVersion().getApplicationCodeName());
43      }
44  
45      /**
46       * Tests the {@code appMinorVersion} property.
47       * @throws Exception on test failure
48       */
49      @Test
50      @Alerts("undefined")
51      public void appMinorVersion() throws Exception {
52          attribute("appMinorVersion", getExpectedAlerts()[0]);
53      }
54  
55      /**
56       * Tests the {@code appName} property.
57       * @throws Exception on test failure
58       */
59      @Test
60      public void appName() throws Exception {
61          attribute("appName", getBrowserVersion().getApplicationName());
62      }
63  
64      /**
65       * Tests the {@code appVersion} property.
66       * @throws Exception on test failure
67       */
68      @Test
69      public void appVersion() throws Exception {
70          attribute("appVersion", getBrowserVersion().getApplicationVersion(),
71                  "SLCC2; ", ".NET CLR 2.0.50727; ", ".NET CLR 3.5.30729; ", ".NET CLR 3.0.30729; ",
72                  "Media Center PC 6.0; ", ".NET4.0C; ", ".NET4.0E; ");
73      }
74  
75      /**
76       * Tests the {@code browserLanguage} property.
77       * @throws Exception on test failure
78       */
79      @Test
80      @Alerts("undefined")
81      public void browserLanguage() throws Exception {
82          attribute("browserLanguage", getExpectedAlerts()[0]);
83      }
84  
85      /**
86       * Tests the {@code productSub} property.
87       * @throws Exception on test failure
88       */
89      @Test
90      @Alerts(DEFAULT = {"string", "20100101"},
91              CHROME = {"string", "20030107"},
92              EDGE = {"string", "20030107"})
93      public void productSub() throws Exception {
94          final String html = DOCTYPE_HTML
95              + "<html><head>\n"
96              + "<script>\n"
97              + LOG_TITLE_FUNCTION
98              + "  log(typeof(navigator.productSub));\n"
99              + "  log(navigator.productSub);\n"
100             + "</script>\n"
101             + "</head><body></body>\n"
102             + "</html>";
103 
104         loadPageVerifyTitle2(html);
105     }
106 
107     /**
108      * Tests the {@code cpuClass} property.
109      * @throws Exception on test failure
110      */
111     @Test
112     @Alerts("undefined")
113     public void cpuClass() throws Exception {
114         attribute("cpuClass", getExpectedAlerts()[0]);
115     }
116 
117     /**
118      * Tests the {@code onLine} property.
119      * @throws Exception on test failure
120      */
121     @Test
122     public void onLine() throws Exception {
123         attribute("onLine", String.valueOf(getBrowserVersion().isOnLine()));
124     }
125 
126     /**
127      * Tests the {@code platform} property.
128      * @throws Exception on test failure
129      */
130     @Test
131     public void platform() throws Exception {
132         attribute("platform", getBrowserVersion().getPlatform());
133     }
134 
135     /**
136      * Tests the {@code systemLanguage} property.
137      * @throws Exception on test failure
138      */
139     @Test
140     @Alerts("undefined")
141     public void systemLanguage() throws Exception {
142         attribute("systemLanguage", getExpectedAlerts()[0]);
143     }
144 
145     /**
146      * Tests the {@code userAgent} property.
147      * @throws Exception on test failure
148      */
149     @Test
150     public void userAgent() throws Exception {
151         attribute("userAgent", getBrowserVersion().getUserAgent(),
152                 "SLCC2; ", ".NET CLR 2.0.50727; ", ".NET CLR 3.5.30729; ", ".NET CLR 3.0.30729; ",
153                 "Media Center PC 6.0; ", ".NET4.0C; ", ".NET4.0E; ");
154     }
155 
156     /**
157      * Tests the {@code userLanguage} property.
158      * @throws Exception on test failure
159      */
160     @Test
161     @Alerts("undefined")
162     public void userLanguage() throws Exception {
163         attribute("userLanguage", getExpectedAlerts()[0]);
164     }
165 
166     /**
167      * Tests the {@code plugins} property.
168      * @throws Exception on test failure
169      */
170     @Test
171     @Alerts({"5",
172         "PDF Viewer", "Portable Document Format", "internal-pdf-viewer", "undefined",
173         "Chrome PDF Viewer", "Portable Document Format", "internal-pdf-viewer", "undefined",
174         "Chromium PDF Viewer", "Portable Document Format", "internal-pdf-viewer", "undefined",
175         "Microsoft Edge PDF Viewer", "Portable Document Format", "internal-pdf-viewer", "undefined",
176         "WebKit built-in PDF", "Portable Document Format", "internal-pdf-viewer", "undefined"})
177     public void plugins() throws Exception {
178         final String html = DOCTYPE_HTML
179                 + "<html>\n"
180                 + "<head>\n"
181                 + "  <script>\n"
182                 + LOG_TITLE_FUNCTION
183                 + "    function doTest() {\n"
184                 + "      log(window.navigator.plugins.length);\n"
185                 + "      for (var i = 0; i < window.navigator.plugins.length; i++) {\n"
186                 + "        let pl = window.navigator.plugins[i];\n"
187                 + "        log(pl.name);\n"
188                 + "        log(pl.description);\n"
189                 + "        log(pl.filename);\n"
190                 + "        log(pl.version);\n"
191                 + "      }\n"
192                 + "    }\n"
193                 + "  </script>\n"
194                 + "</head>\n"
195                 + "<body onload='doTest()'>\n"
196                 + "</body>\n"
197                 + "</html>";
198 
199         loadPageVerifyTitle2(html);
200     }
201 
202     /**
203      * Tests the Shockwave Flash plugin property.
204      * @throws Exception on test failure
205      */
206     @Test
207     @Alerts("Shockwave Flash not available")
208     public void pluginsShockwaveFlash() throws Exception {
209         final String html = DOCTYPE_HTML
210                 + "<html>\n"
211                 + "<head>\n"
212                 + "  <script>\n"
213                 + LOG_TITLE_FUNCTION
214                 + "  function doTest() {\n"
215                 + "    var flash = false;\n"
216                 + "    for (var i = 0; i < window.navigator.plugins.length; i++) {\n"
217                 + "      var plugin = window.navigator.plugins[i];\n"
218                 + "      if ('Shockwave Flash' == window.navigator.plugins[i].name) {\n"
219                 + "        flash = true;\n"
220                 + "        log(plugin.name);\n"
221                 + "        log(plugin.description);\n"
222                 + "        log(plugin.version);\n"
223                 + "        log(plugin.filename);\n"
224                 + "      }\n"
225                 + "    }\n"
226                 + "    if (!flash) {\n"
227                 + "      log('Shockwave Flash not available');\n"
228                 + "    }\n"
229                 + "  }\n"
230                 + "  </script>\n"
231                 + "</head>\n"
232                 + "<body onload='doTest()'>\n"
233                 + "</body>\n"
234                 + "</html>";
235 
236         loadPageVerifyTitle2(html);
237     }
238 
239     /**
240      * @throws Exception if the test fails
241      */
242     @Test
243     @Alerts({"2",
244              "application/pdf", "Portable Document Format", "pdf", "[object Plugin]", "true",
245              "text/pdf", "Portable Document Format", "pdf", "[object Plugin]", "true"})
246     public void mimeTypes() throws Exception {
247         final String html = DOCTYPE_HTML
248                 + "<html><head>\n"
249                 + "  <script>\n"
250                 + LOG_TITLE_FUNCTION
251                 + "    function doTest() {\n"
252                 + "      log(window.navigator.mimeTypes.length);\n"
253                 + "      for (var i = 0; i < window.navigator.mimeTypes.length; i++) {\n"
254                 + "        let mt = window.navigator.mimeTypes[i];\n"
255                 + "        log(mt.type);\n"
256                 + "        log(mt.description);\n"
257                 + "        log(mt.suffixes);\n"
258                 + "        log(mt.enabledPlugin);\n"
259                 + "        log(mt.enabledPlugin === window.navigator.plugins[0]);"
260                 + "      }\n"
261                 + "    }\n"
262                 + "  </script>\n"
263             + "</head><body onload='doTest()'></body>\n"
264             + "</html>";
265 
266         loadPageVerifyTitle2(html);
267     }
268 
269     /**
270      * Tests the {@code taintEnabled} property.
271      * @throws Exception on test failure
272      */
273     @Test
274     @Alerts(DEFAULT = "false",
275             CHROME = "TypeError",
276             EDGE = "TypeError")
277     public void taintEnabled() throws Exception {
278         final String html = DOCTYPE_HTML
279                 + "<html>\n"
280                 + "<head>\n"
281                 + "  <script>\n"
282                 + LOG_TITLE_FUNCTION
283                 + "  function doTest() {\n"
284                 + "    try {\n"
285                 + "      log(window.navigator.taintEnabled());\n"
286                 + "    } catch(e) { logEx(e); }\n"
287                 + "  }\n"
288                 + "  </script>\n"
289                 + "</head>\n"
290                 + "<body onload='doTest()'>\n"
291                 + "</body>\n"
292                 + "</html>";
293 
294         loadPageVerifyTitle2(html);
295     }
296 
297     /**
298      * Generic method for testing the value of a specific navigator attribute.
299      * @param name the name of the attribute to test
300      * @param value the expected value for the named attribute
301      * @throws Exception on test failure
302      */
303     void attribute(final String name, final String value, final String... ignore) throws Exception {
304         final String html = DOCTYPE_HTML
305                 + "<html>\n"
306                 + "<head>\n"
307                 + "  <script>\n"
308                 + LOG_TITLE_FUNCTION
309                 + "    function doTest() {\n"
310                 + "      log(window.navigator." + name + ");\n"
311                 + "    }\n"
312                 + "  </script>\n"
313                 + "</head>\n"
314                 + "<body onload='doTest()'>\n"
315                 + "</body>\n"
316                 + "</html>";
317 
318         setExpectedAlerts(value);
319         loadPageVerifyTitle2(html);
320     }
321 
322     /**
323      * Test {@code language} property.
324      * @throws Exception if the test fails
325      */
326     @Test
327     @Alerts("en-US")
328     public void language() throws Exception {
329         final String html = DOCTYPE_HTML
330             + "<html><head>\n"
331             + "  <script>\n"
332             + LOG_TITLE_FUNCTION
333             + "  </script>\n"
334             + "</head>\n"
335             + "<body onload='log(window.navigator.language)'></body>\n"
336             + "</html>";
337 
338         loadPageVerifyTitle2(html);
339     }
340 
341     /**
342      * Test {@code language} property.
343      * @throws Exception if the test fails
344      */
345     @Test
346     @Alerts("en-US,en")
347     public void languages() throws Exception {
348         final String html = DOCTYPE_HTML
349             + "<html><head>\n"
350             + "  <script>\n"
351             + LOG_TITLE_FUNCTION
352             + "  </script>\n"
353             + "</head>\n"
354             + "<body onload='log(window.navigator.languages)'></body>\n"
355             + "</html>";
356 
357         loadPageVerifyTitle2(html);
358     }
359 
360     /**
361      * @throws Exception if the test fails
362      */
363     @Test
364     @Alerts({"number", "number"})
365     public void mozilla() throws Exception {
366         final String html = DOCTYPE_HTML
367             + "<html><head>\n"
368             + "<script>\n"
369             + LOG_TITLE_FUNCTION
370             + "function test() {\n"
371             + "  log(typeof window.navigator.mimeTypes.length);\n"
372             + "  log(typeof window.navigator.plugins.length);\n"
373             + "}\n"
374             + "</script>\n"
375             + "</head><body onload='test()'></body>\n"
376             + "</html>";
377 
378         loadPageVerifyTitle2(html);
379     }
380 
381     /**
382      * @throws Exception if the test fails
383      */
384     @Test
385     @Alerts("Gecko")
386     public void product() throws Exception {
387         final String html = DOCTYPE_HTML
388             + "<html><head>\n"
389             + "<script>\n"
390             + LOG_TITLE_FUNCTION
391             + "function test() {\n"
392             + "  log(navigator.product);\n"
393             + "}\n"
394             + "</script>\n"
395             + "</head><body onload='test()'></body>\n"
396             + "</html>";
397 
398         loadPageVerifyTitle2(html);
399     }
400 
401     /**
402      * @throws Exception if the test fails
403      */
404     @Test
405     @Alerts("[object Geolocation]")
406     public void geolocation() throws Exception {
407         final String html = DOCTYPE_HTML
408             + "<html><head>\n"
409             + "<script>\n"
410             + LOG_TITLE_FUNCTION
411             + "function test() {\n"
412             + "  log(navigator.geolocation);\n"
413             + "}\n"
414             + "</script>\n"
415             + "</head><body onload='test()'></body>\n"
416             + "</html>";
417 
418         loadPageVerifyTitle2(html);
419     }
420 
421     /**
422      * @throws Exception if the test fails
423      */
424     @Test
425     @Alerts(DEFAULT = "undefined",
426             FF = "20181001000000",
427             FF_ESR = "20181001000000")
428     public void buildID() throws Exception {
429         final String html = DOCTYPE_HTML
430             + "<html><head>\n"
431             + "<script>\n"
432             + LOG_TITLE_FUNCTION
433             + "function test() {\n"
434             + "  log(navigator.buildID);\n"
435             + "}\n"
436             + "</script>\n"
437             + "</head><body onload='test()'></body>\n"
438             + "</html>";
439 
440         loadPageVerifyTitle2(html);
441     }
442 
443     /**
444      * @throws Exception if the test fails
445      */
446     @Test
447     @Alerts(DEFAULT = {"Google Inc.", ""},
448             FF = {"", ""},
449             FF_ESR = {"", ""})
450     public void vendor() throws Exception {
451         final String html = DOCTYPE_HTML
452             + "<html><head>\n"
453             + "<script>\n"
454             + LOG_TITLE_FUNCTION
455             + "function test() {\n"
456             + "  log(navigator.vendor);\n"
457             + "  log(navigator.vendorSub);\n"
458             + "}\n"
459             + "</script>\n"
460             + "</head><body onload='test()'></body>\n"
461             + "</html>";
462 
463         loadPageVerifyTitle2(html);
464     }
465 
466     /**
467      * @throws Exception if the test fails
468      */
469     @Test
470     @Alerts(DEFAULT = "false",
471             FF = "true",
472             FF_ESR = "true")
473     public void oscpu() throws Exception {
474         final String html = DOCTYPE_HTML
475             + "<html><head>\n"
476             + "<script>\n"
477             + LOG_TITLE_FUNCTION
478             + "function test() {\n"
479             + "  log(navigator.oscpu != undefined);\n"
480             + "}\n"
481             + "</script>\n"
482             + "</head><body onload='test()'></body>\n"
483             + "</html>";
484 
485         loadPageVerifyTitle2(html);
486     }
487 
488     /**
489      * @throws Exception if the test fails
490      */
491     @Test
492     @Alerts(DEFAULT = {"undefined", "undefined", "undefined"},
493             CHROME = {"[object NetworkInformation]", "undefined", "undefined"},
494             EDGE = {"[object NetworkInformation]", "undefined", "undefined"})
495     public void connection() throws Exception {
496         final String html = DOCTYPE_HTML
497             + "<html><head>\n"
498             + "<script>\n"
499             + LOG_TITLE_FUNCTION
500             + "  function test() {\n"
501             + "    log(navigator.connection);\n"
502             + "    log(navigator.mozConnection);\n"
503             + "    log(navigator.webkitConnection);\n"
504             + "  }\n"
505             + "</script>\n"
506             + "</head><body onload='test()'>\n"
507             + "</body></html>";
508 
509         loadPageVerifyTitle2(html);
510     }
511 
512     /**
513      * @throws Exception if the test fails
514      */
515     @Test
516     @Alerts(DEFAULT = {"unspecified", "undefined", "undefined"},
517             CHROME = {"null", "undefined", "undefined"},
518             EDGE = {"null", "undefined", "undefined"})
519     public void doNotTrack() throws Exception {
520         final String html = DOCTYPE_HTML
521             + "<html><head>\n"
522             + "<script>\n"
523             + LOG_TITLE_FUNCTION
524             + "  function test() {\n"
525             + "    log(navigator.doNotTrack);\n"
526             + "    log(navigator.msDoNotTrack);\n"
527             + "    log(window.doNotTrack);\n"
528             + "  }\n"
529             + "</script>\n"
530             + "</head><body onload='test()'>\n"
531             + "</body></html>";
532 
533         loadPageVerifyTitle2(html);
534     }
535 
536     /**
537      * @throws Exception if the test fails
538      */
539     @Test
540     @Alerts({"[object MediaDevices]", "true"})
541     public void mediaDevices() throws Exception {
542         final String html = DOCTYPE_HTML
543             + "<html><head>\n"
544             + "<script>\n"
545             + LOG_TITLE_FUNCTION
546             + "  function test() {\n"
547             + "    log(navigator.mediaDevices);\n"
548             + "    log(navigator.mediaDevices === navigator.mediaDevices);\n"
549             + "  }\n"
550             + "</script>\n"
551             + "</head><body onload='test()'>\n"
552             + "</body></html>";
553 
554         loadPageVerifyTitle2(html);
555     }
556 
557     /**
558      * @throws Exception if the test fails
559      */
560     @Test
561     @Alerts("true")
562     public void pdfViewerEnabled() throws Exception {
563         final String html = DOCTYPE_HTML
564             + "<html><head>\n"
565             + "<script>\n"
566             + LOG_TITLE_FUNCTION
567             + "  function test() {\n"
568             + "    log(navigator.pdfViewerEnabled);\n"
569             + "  }\n"
570             + "</script>\n"
571             + "</head><body onload='test()'>\n"
572             + "</body></html>";
573 
574         loadPageVerifyTitle2(html);
575     }
576 }