Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ios / web / web_state / js / resources / window_open_ui.js
blob7eb89ccaf04e06e33024e0f4ab0d72d3d257d54c
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 // Scripts that are conceptually part of core.js, but have UIWebView-specific
6 // details/behaviors.
8 goog.provide('__crWeb.windowOpen');
10 goog.require('__crWeb.core');
12 // Namespace for this module.
13 __gCrWeb.windowOpen = {};
15 // Beginning of anonymous object.
16 (function() {
17   // Preserve a reference to the original window.open method.
18   __gCrWeb['originalWindowOpen'] = window.open;
20   // Object used to keep track of all windows opened from this window.
21   var openedWindows = {};
23   /**
24    * Checks if a child window exists with the given name and if so, sets its
25    * closed property to true and removes it from |openedWindows|.
26    * @param {String} windowName The name of the window to mark as closed.
27    */
28   __gCrWeb['windowClosed'] = function(windowName) {
29     if (openedWindows.hasOwnProperty(windowName)) {
30       openedWindows[windowName].closed = true;
31       delete openedWindows[windowName];
32     }
33   };
35   function invokeOnHost_(command) {
36     __gCrWeb.message.invokeOnHost(command);
37   };
39   var invokeNotImplementedOnHost_ = function(methodName) {
40     invokeOnHost_({'command': 'window.error',
41                    'message': methodName + ' is not implemented'});
42   };
44   // Define Object watch/unwatch functions to detect assignments to
45   // certain object properties. Handles defineProperty case only because
46   // this code runs in UIWebView (i.e. Safari).
47   var objectWatch = function(obj, prop, handler) {
48     var val = obj[prop];
49     if (delete obj[prop]) {
50       Object['defineProperty'](obj, prop, {
51         'get': function() {
52           return val;
53         },
54         'set': function(newVal) {
55           return val = handler.call(obj, prop, val, newVal);
56         }
57       });
58     }
59   };
61   /**
62    * Creates and returns a window proxy used to represent the window object and
63    * intercept calls made on it.
64    * @param {String} target The name of the window.
65    * @return {Object} A window proxy object for intercepting window methods.
66    * @private
67    */
68   var createWindowProxy_ = function(target) {
69     // Create return window object.
70     // 'name' is always the original supplied name.
71     var windowProxy = {name: target};
73     // Define window object methods.
74     windowProxy.alert = function() {
75       invokeNotImplementedOnHost_('windowProxy.alert');
76     };
78     windowProxy.blur = function() {
79       invokeNotImplementedOnHost_('windowProxy.blur');
80     };
82     windowProxy.clearInterval = function() {
83       invokeNotImplementedOnHost_('windowProxy.clearInterval');
84     };
86     windowProxy.clearTimeout = function() {
87       invokeNotImplementedOnHost_('windowProxy.clearTimeout');
88     };
90     windowProxy.close = function() {
91       invokeOnHost_({'command': 'window.close',
92                      'target': target});
93     };
95     windowProxy.confirm = function() {
96       invokeNotImplementedOnHost_('windowProxy.confirm');
97     };
99     windowProxy.createPopup = function() {
100       invokeNotImplementedOnHost_('windowProxy.createPopup');
101     };
103     windowProxy.focus = function() {
104       // Noop as the opened window always gets focus.
105     };
107     windowProxy.moveBy = function() {
108       invokeNotImplementedOnHost_('windowProxy.moveBy');
109     };
111     windowProxy.moveTo = function() {
112       invokeNotImplementedOnHost_('windowProxy.moveTo');
113     };
115     windowProxy.stop = function() {
116       invokeOnHost_({'command': 'window.stop',
117                      'target': target});
118     };
120     windowProxy.open = function() {
121       invokeNotImplementedOnHost_('windowProxy.open');
122     };
124     windowProxy.print = function() {
125       invokeNotImplementedOnHost_('windowProxy.print');
126     };
128     windowProxy.prompt = function() {
129       invokeNotImplementedOnHost_('windowProxy.prompt');
130     };
132     windowProxy.resizeBy = function() {
133       invokeNotImplementedOnHost_('windowProxy.resizeBy');
134     };
136     windowProxy.resizeTo = function() {
137       invokeNotImplementedOnHost_('windowProxy.resizeTo');
138     };
140     windowProxy.scroll = function() {
141       invokeNotImplementedOnHost_('windowProxy.scroll');
142     };
144     windowProxy.scrollBy = function() {
145       invokeNotImplementedOnHost_('windowProxy.scrollBy');
146     };
148     windowProxy.scrollTo = function() {
149       invokeNotImplementedOnHost_('windowProxy.scrollTo');
150     };
152     windowProxy.setInterval = function() {
153       invokeNotImplementedOnHost_('windowProxy.setInterval');
154     };
156     windowProxy.setTimeout = function() {
157       invokeNotImplementedOnHost_('windowProxy.setTimeout');
158     };
160     // Define window object properties.
161     // The current window.
162     windowProxy.self = windowProxy;
163     // The topmost browser window.
164     windowProxy.top = windowProxy;
166     // Provide proxy document which supplies one method, document.write().
167     windowProxy.document = {};
168     windowProxy.document.title = '';
169     windowProxy.document.write = function(html) {
170       invokeOnHost_({'command': 'window.document.write',
171                        'html': html,
172                      'target': target});
173     };
175     windowProxy.document.open = function() {
176       // The open() method should open an output stream to collect the output
177       // from any document.write() or document.writeln() methods.
178       invokeNotImplementedOnHost_('windowProxy.document.open');
179     };
181     windowProxy.document.close = function() {
182       // The close() method should close the output stream previously opened
183       // with the document.open() method, and displays the collected data in
184       // this process.
185       invokeNotImplementedOnHost_('windowProxy.document.close');
186     };
188     windowProxy.location = {};
189     windowProxy.location.assign = function(url) {
190       windowProxy.location = url;
191     };
192     // Watch assignments to window.location and window.location.href.
193     // Invoke equivalent method in ObjC code.
194     var onWindowProxyLocationChange = function(prop, oldVal, newVal) {
195       invokeOnHost_({'command': 'window.location',
196                      'value': __gCrWeb['getFullyQualifiedURL'](newVal),
197                      'target': target});
198       return newVal;
199     };
200     objectWatch(windowProxy, 'location', onWindowProxyLocationChange);
201     objectWatch(windowProxy.location, 'href', onWindowProxyLocationChange);
202     windowProxy.closed = false;
204     return windowProxy;
205   };
207   // Intercept window.open calls.
208   window.open = function(url, target, features) {
209     if (target == '_parent' || target == '_self' || target == '_top') {
210       return __gCrWeb['originalWindowOpen'].call(window, url, target, features);
211     }
213     // Because of the difficulty of returning data from JS->ObjC calls, in the
214     // event of a blank window name the JS side chooses a pseudo-GUID to
215     // use as the window name which is passed to ObjC and mapped to the real
216     // Tab there.
217     var isTargetBlank = (typeof target == 'undefined' || target == '_blank' ||
218                          target == '' || target == null);
219     if (isTargetBlank) {
220       target = '' + Date.now() + '-' + Math.random();
221     }
223     if (typeof(url) == 'undefined') {
224       // W3C recommended behavior.
225       url = 'about:blank';
226     }
228     invokeOnHost_({
229       'command': 'window.open',
230       'target': target,
231       'url': url,
232       'referrerPolicy': __gCrWeb.getPageReferrerPolicy()
233     });
235     // Create a new |windowProxy| if none already exists with |target| as its
236     // name.
237     var windowProxy;
238     if (openedWindows.hasOwnProperty(target)) {
239       windowProxy = openedWindows[target];
240     } else {
241       windowProxy = createWindowProxy_(target);
242       openedWindows[target] = windowProxy;
243     }
244     return windowProxy;
245   };
247 }());  // End of anonymous object