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.
18 * Install a wrapper around functions displaying dialogs in order to catch
19 * code displaying dialog.
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.
25 * Returns a function that allows changing the value of the two booleans
26 * |suppressDialogs| and |notifyAboutDialogs| that are tested by the wrappers.
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) {
36 if (!suppressDialogs) {
37 if (notifyAboutDialogs) {
38 __gCrWeb.message.invokeOnHost({'command': 'dialog.willShow'});
40 return originalDialogGetter().apply(null, arguments);
41 } else if (notifyAboutDialogs) {
42 __gCrWeb.message.invokeOnHost({'command': 'dialog.suppressed'});
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]);
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
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);
75 Object['defineProperty'](stubNavigator, keyName, {
85 // Stub in 'geolocation' if necessary, using delayed accessor for the
86 // 'geolocation' property of the original |navigator|.
87 if ('geolocation' in navigator) {
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() {
95 return oldNavigator.geolocation[geoPropName].apply(
96 oldNavigator.geolocation, arguments);
101 stubNavigator.geolocation = geolocation;
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;
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