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
8 goog.provide('__crWeb.windowOpen');
10 goog.require('__crWeb.core');
12 // Namespace for this module.
13 __gCrWeb.windowOpen = {};
15 // Beginning of anonymous object.
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 = {};
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.
28 __gCrWeb['windowClosed'] = function(windowName) {
29 if (openedWindows.hasOwnProperty(windowName)) {
30 openedWindows[windowName].closed = true;
31 delete openedWindows[windowName];
35 function invokeOnHost_(command) {
36 __gCrWeb.message.invokeOnHost(command);
39 var invokeNotImplementedOnHost_ = function(methodName) {
40 invokeOnHost_({'command': 'window.error',
41 'message': methodName + ' is not implemented'});
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) {
49 if (delete obj[prop]) {
50 Object['defineProperty'](obj, prop, {
54 'set': function(newVal) {
55 return val = handler.call(obj, prop, val, newVal);
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.
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');
78 windowProxy.blur = function() {
79 invokeNotImplementedOnHost_('windowProxy.blur');
82 windowProxy.clearInterval = function() {
83 invokeNotImplementedOnHost_('windowProxy.clearInterval');
86 windowProxy.clearTimeout = function() {
87 invokeNotImplementedOnHost_('windowProxy.clearTimeout');
90 windowProxy.close = function() {
91 invokeOnHost_({'command': 'window.close',
95 windowProxy.confirm = function() {
96 invokeNotImplementedOnHost_('windowProxy.confirm');
99 windowProxy.createPopup = function() {
100 invokeNotImplementedOnHost_('windowProxy.createPopup');
103 windowProxy.focus = function() {
104 // Noop as the opened window always gets focus.
107 windowProxy.moveBy = function() {
108 invokeNotImplementedOnHost_('windowProxy.moveBy');
111 windowProxy.moveTo = function() {
112 invokeNotImplementedOnHost_('windowProxy.moveTo');
115 windowProxy.stop = function() {
116 invokeOnHost_({'command': 'window.stop',
120 windowProxy.open = function() {
121 invokeNotImplementedOnHost_('windowProxy.open');
124 windowProxy.print = function() {
125 invokeNotImplementedOnHost_('windowProxy.print');
128 windowProxy.prompt = function() {
129 invokeNotImplementedOnHost_('windowProxy.prompt');
132 windowProxy.resizeBy = function() {
133 invokeNotImplementedOnHost_('windowProxy.resizeBy');
136 windowProxy.resizeTo = function() {
137 invokeNotImplementedOnHost_('windowProxy.resizeTo');
140 windowProxy.scroll = function() {
141 invokeNotImplementedOnHost_('windowProxy.scroll');
144 windowProxy.scrollBy = function() {
145 invokeNotImplementedOnHost_('windowProxy.scrollBy');
148 windowProxy.scrollTo = function() {
149 invokeNotImplementedOnHost_('windowProxy.scrollTo');
152 windowProxy.setInterval = function() {
153 invokeNotImplementedOnHost_('windowProxy.setInterval');
156 windowProxy.setTimeout = function() {
157 invokeNotImplementedOnHost_('windowProxy.setTimeout');
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',
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');
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
185 invokeNotImplementedOnHost_('windowProxy.document.close');
188 windowProxy.location = {};
189 windowProxy.location.assign = function(url) {
190 windowProxy.location = url;
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),
200 objectWatch(windowProxy, 'location', onWindowProxyLocationChange);
201 objectWatch(windowProxy.location, 'href', onWindowProxyLocationChange);
202 windowProxy.closed = false;
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);
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
217 var isTargetBlank = (typeof target == 'undefined' || target == '_blank' ||
218 target == '' || target == null);
220 target = '' + Date.now() + '-' + Math.random();
223 if (typeof(url) == 'undefined') {
224 // W3C recommended behavior.
229 'command': 'window.open',
232 'referrerPolicy': __gCrWeb.getPageReferrerPolicy()
235 // Create a new |windowProxy| if none already exists with |target| as its
238 if (openedWindows.hasOwnProperty(target)) {
239 windowProxy = openedWindows[target];
241 windowProxy = createWindowProxy_(target);
242 openedWindows[target] = windowProxy;
247 }()); // End of anonymous object