Fix breakages in https://codereview.chromium.org/1155713003/
[chromium-blink-merge.git] / ios / web / web_state / js / resources / dialog_overrides.js
blob561e7c98707b4c3e68ca3c40fcce97f36aad53db
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 goog.provide('__crWeb.dialogOverrides');
7 goog.require('__crWeb.core');
8 // window.open override for dialog suppression must be performed after the rest
9 // of window.open overrides which are done in __crWeb.windowOpen module.
10 goog.require('__crWeb.windowOpen');
12 // Namespace for this module.
13 __gCrWeb.dialogOverrides = {};
15 // Beginning of anonymous object.
16 new function() {
17   /*
18    * Install a wrapper around functions displaying dialogs in order to catch
19    * code displaying dialog.
20    *
21    * Since the Javascript on the page may cache the value of those functions
22    * and invoke them later, we must only install the wrapper once and change
23    * their behaviour when required.
24    *
25    * Returns a function that allows changing the value of the two booleans
26    * |suppressDialogs| and |notifyAboutDialogs| that are tested by the wrappers.
27    */
28   var installDialogOverridesMethods = function() {
29     var suppressDialogs = false;
30     var notifyAboutDialogs = false;
32     // Returns a wrapper function around |originalDialog|. The wrapper may
33     // suppress the dialog and notify host about show/suppress.
34     var makeDialogWrapper = function(originalDialogGetter) {
35       return function() {
36         if (!suppressDialogs) {
37           if (notifyAboutDialogs) {
38             __gCrWeb.message.invokeOnHost({'command': 'dialog.willShow'});
39           }
40           return originalDialogGetter().apply(null, arguments);
41         } else if (notifyAboutDialogs) {
42           __gCrWeb.message.invokeOnHost({'command': 'dialog.suppressed'});
43         }
44       };
45     };
47     // Install wrapper around the following properties of |window|.
48     var wrappedFunctionNames = ['alert', 'confirm', 'prompt', 'open'];
49     var len = wrappedFunctionNames.length;
50     for (var i = 0; i < len; i++) {
51       (function(wrappedFunctionName) {
52         var wrappedDialogMethod = window[wrappedFunctionName];
53         window[wrappedFunctionName] = makeDialogWrapper(
54           function() { return wrappedDialogMethod; });
55       })(wrappedFunctionNames[i]);
56     }
58     // Reading or writing to the property 'geolocation' too early breaks
59     // the API. Make a copy of navigator and stub in the required methods
60     // without touching the property. See crbug.com/280818 for more
61     // details.
62     var stubNavigator = {};
64     // Copy all properties and functions without touching 'geolocation'.
65     var oldNavigator = navigator;
66     for (var keyName in navigator) {
67       if (keyName !== 'geolocation') {
68         var value = navigator[keyName];
69         if (typeof(value) == 'function') {
70           // Forward functions calls to real navigator.
71           stubNavigator[keyName] = function() {
72             return value.apply(oldNavigator, arguments);
73           }
74         } else {
75           Object['defineProperty'](stubNavigator, keyName, {
76             value: value,
77             configurable: false,
78             writable: false,
79             enumerable: true
80           });
81         }
82       }
83     }
85     // Stub in 'geolocation' if necessary, using delayed accessor for the
86     // 'geolocation' property of the original |navigator|.
87     if ('geolocation' in navigator) {
88       var geolocation = {};
89       var geoPropNames = ['getCurrentPosition', 'watchPosition', 'clearWatch'];
90       var len = geoPropNames.length;
91       for (var i = 0; i < len; i++) {
92         (function(geoPropName) {
93           geolocation[geoPropName] = makeDialogWrapper(function() {
94              return function() {
95                return oldNavigator.geolocation[geoPropName].apply(
96                    oldNavigator.geolocation, arguments);
97              };
98           });
99         })(geoPropNames[i]);
100       }
101       stubNavigator.geolocation = geolocation;
102     }
104     // Install |stubNavigator| as |navigator|.
105     /** @suppress {const} */
106     navigator = stubNavigator;
108     // Returns the closure allowing to change |suppressDialogs| and
109     // |notifyAboutDialogs| variables.
110     return function(setEnabled, setNotify) {
111       suppressDialogs = setEnabled;
112       notifyAboutDialogs = setNotify;
113     };
114   };
116   // Override certain methods that produce dialogs. This needs to be installed
117   // after other window methods overrides.
118   __gCrWeb['setSuppressDialogs'] = installDialogOverridesMethods();
120 }  // End of anonymous object