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