| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // This module implements a wrapper for a guestview that manages its | 5 // This module implements a wrapper for a guestview that manages its |
| 6 // creation, attaching, and destruction. | 6 // creation, attaching, and destruction. |
| 7 | 7 |
| 8 var CreateEvent = require('guestViewEvents').CreateEvent; | 8 var CreateEvent = require('guestViewEvents').CreateEvent; |
| 9 var EventBindings = require('event_bindings'); | 9 var EventBindings = require('event_bindings'); |
| 10 var GuestViewInternal = | 10 var GuestViewInternal = |
| 11 require('binding').Binding.create('guestViewInternal').generate(); | 11 require('binding').Binding.create('guestViewInternal').generate(); |
| 12 var GuestViewInternalNatives = requireNative('guest_view_internal'); | 12 var GuestViewInternalNatives = requireNative('guest_view_internal'); |
| 13 | 13 |
| 14 // Events. | 14 // Events. |
| 15 var ResizeEvent = CreateEvent('guestViewInternal.onResize'); | 15 var ResizeEvent = CreateEvent('guestViewInternal.onResize'); |
| 16 | 16 |
| 17 // Possible states. | |
| 18 var GUEST_STATE_ATTACHED = 2; | |
| 19 var GUEST_STATE_CREATED = 1; | |
| 20 var GUEST_STATE_START = 0; | |
| 21 | |
| 22 // Error messages. | 17 // Error messages. |
| 23 var ERROR_MSG_ALREADY_ATTACHED = 'The guest has already been attached.'; | 18 var ERROR_MSG_ALREADY_ATTACHED = 'The guest has already been attached.'; |
| 24 var ERROR_MSG_ALREADY_CREATED = 'The guest has already been created.'; | 19 var ERROR_MSG_ALREADY_CREATED = 'The guest has already been created.'; |
| 25 var ERROR_MSG_INVALID_STATE = 'The guest is in an invalid state.'; | 20 var ERROR_MSG_INVALID_STATE = 'The guest is in an invalid state.'; |
| 26 var ERROR_MSG_NOT_ATTACHED = 'The guest is not attached.'; | 21 var ERROR_MSG_NOT_ATTACHED = 'The guest is not attached.'; |
| 27 var ERROR_MSG_NOT_CREATED = 'The guest has not been created.'; | 22 var ERROR_MSG_NOT_CREATED = 'The guest has not been created.'; |
| 28 | 23 |
| 29 // Properties. | 24 // Properties. |
| 30 var PROPERTY_ON_RESIZE = 'onresize'; | 25 var PROPERTY_ON_RESIZE = 'onresize'; |
| 31 | 26 |
| 32 // Contains and hides the internal implementation details of |GuestView|, | 27 // Contains and hides the internal implementation details of |GuestView|, |
| 33 // including maintaining its state and enforcing the proper usage of its API | 28 // including maintaining its state and enforcing the proper usage of its API |
| 34 // fucntions. | 29 // fucntions. |
| 35 function GuestViewImpl(guestView, viewType, guestInstanceId) { | 30 function GuestViewImpl(guestView, viewType, guestInstanceId) { |
| 36 if (guestInstanceId) { | 31 if (guestInstanceId) { |
| 37 this.id = guestInstanceId; | 32 this.id = guestInstanceId; |
| 38 this.state = GUEST_STATE_CREATED; | 33 this.state = GuestViewImpl.GuestState.GUEST_STATE_CREATED; |
| 39 } else { | 34 } else { |
| 40 this.id = 0; | 35 this.id = 0; |
| 41 this.state = GUEST_STATE_START; | 36 this.state = GuestViewImpl.GuestState.GUEST_STATE_START; |
| 42 } | 37 } |
| 43 this.actionQueue = []; | 38 this.actionQueue = []; |
| 44 this.contentWindow = null; | 39 this.contentWindow = null; |
| 45 this.guestView = guestView; | 40 this.guestView = guestView; |
| 46 this.pendingAction = null; | 41 this.pendingAction = null; |
| 47 this.viewType = viewType; | 42 this.viewType = viewType; |
| 48 this.internalInstanceId = 0; | 43 this.internalInstanceId = 0; |
| 49 | 44 |
| 50 this.setupOnResize(); | 45 this.setupOnResize(); |
| 51 } | 46 } |
| 52 | 47 |
| 48 // Possible states. |
| 49 GuestViewImpl.GuestState = { |
| 50 GUEST_STATE_START: 0, |
| 51 GUEST_STATE_CREATED: 1, |
| 52 GUEST_STATE_ATTACHED: 2 |
| 53 }; |
| 54 |
| 53 // Sets up the onResize property on the GuestView. | 55 // Sets up the onResize property on the GuestView. |
| 54 GuestViewImpl.prototype.setupOnResize = function() { | 56 GuestViewImpl.prototype.setupOnResize = function() { |
| 55 $Object.defineProperty(this.guestView, PROPERTY_ON_RESIZE, { | 57 $Object.defineProperty(this.guestView, PROPERTY_ON_RESIZE, { |
| 56 get: function() { | 58 get: function() { |
| 57 return this[PROPERTY_ON_RESIZE]; | 59 return this[PROPERTY_ON_RESIZE]; |
| 58 }.bind(this), | 60 }.bind(this), |
| 59 set: function(value) { | 61 set: function(value) { |
| 60 this[PROPERTY_ON_RESIZE] = value; | 62 this[PROPERTY_ON_RESIZE] = value; |
| 61 }.bind(this), | 63 }.bind(this), |
| 62 enumerable: true | 64 enumerable: true |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 var view = GuestViewInternalNatives.GetViewFromID(viewInstanceId); | 140 var view = GuestViewInternalNatives.GetViewFromID(viewInstanceId); |
| 139 if (view && view.guest) { | 141 if (view && view.guest) { |
| 140 return $Function.apply(func, | 142 return $Function.apply(func, |
| 141 privates(view.guest).internal, | 143 privates(view.guest).internal, |
| 142 $Array.slice(arguments)); | 144 $Array.slice(arguments)); |
| 143 } | 145 } |
| 144 }; | 146 }; |
| 145 }; | 147 }; |
| 146 | 148 |
| 147 // Internal implementation of attach(). | 149 // Internal implementation of attach(). |
| 148 GuestViewImpl.prototype.attachImpl = function( | 150 GuestViewImpl.prototype.attachImpl$ = function( |
| 149 internalInstanceId, viewInstanceId, attachParams, callback) { | 151 internalInstanceId, viewInstanceId, attachParams, callback) { |
| 150 // Check the current state. | 152 // Check the current state. |
| 151 if (!this.checkState('attach')) { | 153 if (!this.checkState('attach')) { |
| 152 this.handleCallback(callback); | 154 this.handleCallback(callback); |
| 153 return; | 155 return; |
| 154 } | 156 } |
| 155 | 157 |
| 156 // Callback wrapper function to store the contentWindow from the attachGuest() | 158 // Callback wrapper function to store the contentWindow from the attachGuest() |
| 157 // callback, handle potential attaching failure, register an automatic detach, | 159 // callback, handle potential attaching failure, register an automatic detach, |
| 158 // and advance the queue. | 160 // and advance the queue. |
| 159 var callbackWrapper = function(callback, contentWindow) { | 161 var callbackWrapper = function(callback, contentWindow) { |
| 160 // Check if attaching failed. | 162 // Check if attaching failed. |
| 161 if (!contentWindow) { | 163 if (!contentWindow) { |
| 162 this.state = GUEST_STATE_CREATED; | 164 this.state = GuestViewImpl.GuestState.GUEST_STATE_CREATED; |
| 163 this.internalInstanceId = 0; | 165 this.internalInstanceId = 0; |
| 164 } else { | 166 } else { |
| 165 // Only update the contentWindow if attaching is successful. | 167 // Only update the contentWindow if attaching is successful. |
| 166 this.contentWindow = contentWindow; | 168 this.contentWindow = contentWindow; |
| 167 } | 169 } |
| 168 | 170 |
| 169 this.handleCallback(callback); | 171 this.handleCallback(callback); |
| 170 }; | 172 }; |
| 171 | 173 |
| 172 attachParams['instanceId'] = viewInstanceId; | 174 attachParams['instanceId'] = viewInstanceId; |
| 173 GuestViewInternalNatives.AttachGuest(internalInstanceId, | 175 GuestViewInternalNatives.AttachGuest(internalInstanceId, |
| 174 this.id, | 176 this.id, |
| 175 attachParams, | 177 attachParams, |
| 176 callbackWrapper.bind(this, callback)); | 178 callbackWrapper.bind(this, callback)); |
| 177 | 179 |
| 178 this.internalInstanceId = internalInstanceId; | 180 this.internalInstanceId = internalInstanceId; |
| 179 this.state = GUEST_STATE_ATTACHED; | 181 this.state = GuestViewImpl.GuestState.GUEST_STATE_ATTACHED; |
| 180 | 182 |
| 181 // Detach automatically when the container is destroyed. | 183 // Detach automatically when the container is destroyed. |
| 182 GuestViewInternalNatives.RegisterDestructionCallback( | 184 GuestViewInternalNatives.RegisterDestructionCallback( |
| 183 internalInstanceId, this.weakWrapper(function() { | 185 internalInstanceId, this.weakWrapper(function() { |
| 184 if (this.state != GUEST_STATE_ATTACHED || | 186 if (this.state != GuestViewImpl.GuestState.GUEST_STATE_ATTACHED || |
| 185 this.internalInstanceId != internalInstanceId) { | 187 this.internalInstanceId != internalInstanceId) { |
| 186 return; | 188 return; |
| 187 } | 189 } |
| 188 | 190 |
| 189 this.internalInstanceId = 0; | 191 this.internalInstanceId = 0; |
| 190 this.state = GUEST_STATE_CREATED; | 192 this.state = GuestViewImpl.GuestState.GUEST_STATE_CREATED; |
| 191 }, viewInstanceId)); | 193 }, viewInstanceId)); |
| 192 }; | 194 }; |
| 193 | 195 |
| 194 // Internal implementation of create(). | 196 // Internal implementation of create(). |
| 195 GuestViewImpl.prototype.createImpl = function(createParams, callback) { | 197 GuestViewImpl.prototype.createImpl$ = function(createParams, callback) { |
| 196 // Check the current state. | 198 // Check the current state. |
| 197 if (!this.checkState('create')) { | 199 if (!this.checkState('create')) { |
| 198 this.handleCallback(callback); | 200 this.handleCallback(callback); |
| 199 return; | 201 return; |
| 200 } | 202 } |
| 201 | 203 |
| 202 // Callback wrapper function to store the guestInstanceId from the | 204 // Callback wrapper function to store the guestInstanceId from the |
| 203 // createGuest() callback, handle potential creation failure, and advance the | 205 // createGuest() callback, handle potential creation failure, and advance the |
| 204 // queue. | 206 // queue. |
| 205 var callbackWrapper = function(callback, guestInfo) { | 207 var callbackWrapper = function(callback, guestInfo) { |
| 206 this.id = guestInfo.id; | 208 this.id = guestInfo.id; |
| 207 this.contentWindow = | 209 this.contentWindow = |
| 208 GuestViewInternalNatives.GetContentWindow(guestInfo.contentWindowId); | 210 GuestViewInternalNatives.GetContentWindow(guestInfo.contentWindowId); |
| 209 | 211 |
| 210 // Check if creation failed. | 212 // Check if creation failed. |
| 211 if (this.id === 0) { | 213 if (this.id === 0) { |
| 212 this.state = GUEST_STATE_START; | 214 this.state = GuestViewImpl.GuestState.GUEST_STATE_START; |
| 213 this.contentWindow = null; | 215 this.contentWindow = null; |
| 214 } | 216 } |
| 215 | 217 |
| 216 ResizeEvent.addListener(this.callOnResize, {instanceId: this.id}); | 218 ResizeEvent.addListener(this.callOnResize, {instanceId: this.id}); |
| 217 this.handleCallback(callback); | 219 this.handleCallback(callback); |
| 218 }; | 220 }; |
| 219 | 221 |
| 220 GuestViewInternal.createGuest(this.viewType, | 222 this.sendCreateRequest(createParams, callbackWrapper.bind(this, callback)); |
| 221 createParams, | |
| 222 callbackWrapper.bind(this, callback)); | |
| 223 | 223 |
| 224 this.state = GUEST_STATE_CREATED; | 224 this.state = GuestViewImpl.GuestState.GUEST_STATE_CREATED; |
| 225 }; |
| 226 |
| 227 GuestViewImpl.prototype.sendCreateRequest = function( |
| 228 createParams, boundCallback) { |
| 229 GuestViewInternal.createGuest(this.viewType, createParams, boundCallback); |
| 225 }; | 230 }; |
| 226 | 231 |
| 227 // Internal implementation of destroy(). | 232 // Internal implementation of destroy(). |
| 228 GuestViewImpl.prototype.destroyImpl = function(callback) { | 233 GuestViewImpl.prototype.destroyImpl = function(callback) { |
| 229 // Check the current state. | 234 // Check the current state. |
| 230 if (!this.checkState('destroy')) { | 235 if (!this.checkState('destroy')) { |
| 231 this.handleCallback(callback); | 236 this.handleCallback(callback); |
| 232 return; | 237 return; |
| 233 } | 238 } |
| 234 | 239 |
| 235 if (this.state == GUEST_STATE_START) { | 240 if (this.state == GuestViewImpl.GuestState.GUEST_STATE_START) { |
| 236 // destroy() does nothing in this case. | 241 // destroy() does nothing in this case. |
| 237 this.handleCallback(callback); | 242 this.handleCallback(callback); |
| 238 return; | 243 return; |
| 239 } | 244 } |
| 240 | 245 |
| 241 // If this guest is attached, then detach it first. | 246 // If this guest is attached, then detach it first. |
| 242 if (!!this.internalInstanceId) { | 247 if (!!this.internalInstanceId) { |
| 243 GuestViewInternalNatives.DetachGuest(this.internalInstanceId); | 248 GuestViewInternalNatives.DetachGuest(this.internalInstanceId); |
| 244 } | 249 } |
| 245 | 250 |
| 246 GuestViewInternal.destroyGuest(this.id, | 251 GuestViewInternal.destroyGuest(this.id, |
| 247 this.handleCallback.bind(this, callback)); | 252 this.handleCallback.bind(this, callback)); |
| 248 | 253 |
| 249 // Reset the state of the destroyed guest; | 254 // Reset the state of the destroyed guest; |
| 250 this.contentWindow = null; | 255 this.contentWindow = null; |
| 251 this.id = 0; | 256 this.id = 0; |
| 252 this.internalInstanceId = 0; | 257 this.internalInstanceId = 0; |
| 253 this.state = GUEST_STATE_START; | 258 this.state = GuestViewImpl.GuestState.GUEST_STATE_START; |
| 254 if (ResizeEvent.hasListener(this.callOnResize)) { | 259 if (ResizeEvent.hasListener(this.callOnResize)) { |
| 255 ResizeEvent.removeListener(this.callOnResize); | 260 ResizeEvent.removeListener(this.callOnResize); |
| 256 } | 261 } |
| 257 }; | 262 }; |
| 258 | 263 |
| 259 // Internal implementation of detach(). | 264 // Internal implementation of detach(). |
| 260 GuestViewImpl.prototype.detachImpl = function(callback) { | 265 GuestViewImpl.prototype.detachImpl = function(callback) { |
| 261 // Check the current state. | 266 // Check the current state. |
| 262 if (!this.checkState('detach')) { | 267 if (!this.checkState('detach')) { |
| 263 this.handleCallback(callback); | 268 this.handleCallback(callback); |
| 264 return; | 269 return; |
| 265 } | 270 } |
| 266 | 271 |
| 267 GuestViewInternalNatives.DetachGuest( | 272 GuestViewInternalNatives.DetachGuest( |
| 268 this.internalInstanceId, | 273 this.internalInstanceId, |
| 269 this.handleCallback.bind(this, callback)); | 274 this.handleCallback.bind(this, callback)); |
| 270 | 275 |
| 271 this.internalInstanceId = 0; | 276 this.internalInstanceId = 0; |
| 272 this.state = GUEST_STATE_CREATED; | 277 this.state = GuestViewImpl.GuestState.GUEST_STATE_CREATED; |
| 273 }; | 278 }; |
| 274 | 279 |
| 275 // Internal implementation of setSize(). | 280 // Internal implementation of setSize(). |
| 276 GuestViewImpl.prototype.setSizeImpl = function(sizeParams, callback) { | 281 GuestViewImpl.prototype.setSizeImpl = function(sizeParams, callback) { |
| 277 // Check the current state. | 282 // Check the current state. |
| 278 if (!this.checkState('setSize')) { | 283 if (!this.checkState('setSize')) { |
| 279 this.handleCallback(callback); | 284 this.handleCallback(callback); |
| 280 return; | 285 return; |
| 281 } | 286 } |
| 282 | 287 |
| 283 GuestViewInternal.setSize(this.id, sizeParams, | 288 GuestViewInternal.setSize(this.id, sizeParams, |
| 284 this.handleCallback.bind(this, callback)); | 289 this.handleCallback.bind(this, callback)); |
| 285 }; | 290 }; |
| 286 | 291 |
| 287 // The exposed interface to a guestview. Exposes in its API the functions | 292 // The exposed interface to a guestview. Exposes in its API the functions |
| 288 // attach(), create(), destroy(), and getId(). All other implementation details | 293 // attach(), create(), destroy(), and getId(). All other implementation details |
| 289 // are hidden. | 294 // are hidden. |
| 290 function GuestView(viewType, guestInstanceId) { | 295 function GuestView(viewType, guestInstanceId) { |
| 291 privates(this).internal = new GuestViewImpl(this, viewType, guestInstanceId); | 296 privates(this).internal = new GuestViewImpl(this, viewType, guestInstanceId); |
| 292 } | 297 } |
| 293 | 298 |
| 294 // Attaches the guestview to the container with ID |internalInstanceId|. | 299 // Attaches the guestview to the container with ID |internalInstanceId|. |
| 295 GuestView.prototype.attach = function( | 300 GuestView.prototype.attach = function( |
| 296 internalInstanceId, viewInstanceId, attachParams, callback) { | 301 internalInstanceId, viewInstanceId, attachParams, callback) { |
| 297 var internal = privates(this).internal; | 302 var internal = privates(this).internal; |
| 298 internal.actionQueue.push(internal.attachImpl.bind( | 303 internal.actionQueue.push(internal.attachImpl$.bind( |
| 299 internal, internalInstanceId, viewInstanceId, attachParams, callback)); | 304 internal, internalInstanceId, viewInstanceId, attachParams, callback)); |
| 300 internal.performNextAction(); | 305 internal.performNextAction(); |
| 301 }; | 306 }; |
| 302 | 307 |
| 303 // Creates the guestview. | 308 // Creates the guestview. |
| 304 GuestView.prototype.create = function(createParams, callback) { | 309 GuestView.prototype.create = function(createParams, callback) { |
| 305 var internal = privates(this).internal; | 310 var internal = privates(this).internal; |
| 306 internal.actionQueue.push(internal.createImpl.bind( | 311 internal.actionQueue.push(internal.createImpl$.bind( |
| 307 internal, createParams, callback)); | 312 internal, createParams, callback)); |
| 308 internal.performNextAction(); | 313 internal.performNextAction(); |
| 309 }; | 314 }; |
| 310 | 315 |
| 311 // Destroys the guestview. Nothing can be done with the guestview after it has | 316 // Destroys the guestview. Nothing can be done with the guestview after it has |
| 312 // been destroyed. | 317 // been destroyed. |
| 313 GuestView.prototype.destroy = function(callback) { | 318 GuestView.prototype.destroy = function(callback) { |
| 314 var internal = privates(this).internal; | 319 var internal = privates(this).internal; |
| 315 internal.actionQueue.push(internal.destroyImpl.bind(internal, callback)); | 320 internal.actionQueue.push(internal.destroyImpl.bind(internal, callback)); |
| 316 internal.performNextAction(); | 321 internal.performNextAction(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 339 }; | 344 }; |
| 340 | 345 |
| 341 // Returns the ID for this guestview. | 346 // Returns the ID for this guestview. |
| 342 GuestView.prototype.getId = function() { | 347 GuestView.prototype.getId = function() { |
| 343 var internal = privates(this).internal; | 348 var internal = privates(this).internal; |
| 344 return internal.id; | 349 return internal.id; |
| 345 }; | 350 }; |
| 346 | 351 |
| 347 // Exports | 352 // Exports |
| 348 exports.GuestView = GuestView; | 353 exports.GuestView = GuestView; |
| 354 exports.GuestViewImpl = GuestViewImpl; |
| 355 exports.ResizeEvent = ResizeEvent; |
| OLD | NEW |