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