Upstream version 9.37.195.0
[platform/framework/web/crosswalk.git] / src / chrome / renderer / resources / extensions / web_view.js
index 81b5d3f..ad90bfc 100644 (file)
@@ -19,6 +19,8 @@ var WEB_VIEW_ATTRIBUTE_MINHEIGHT = 'minheight';
 var WEB_VIEW_ATTRIBUTE_MINWIDTH = 'minwidth';
 var WEB_VIEW_ATTRIBUTE_PARTITION = 'partition';
 
+var PLUGIN_METHOD_ATTACH = '-internal-attach';
+
 var ERROR_MSG_ALREADY_NAVIGATED =
     'The object has already navigated, so its partition cannot be changed.';
 var ERROR_MSG_INVALID_PARTITION_ATTRIBUTE = 'Invalid partition attribute.';
@@ -87,6 +89,11 @@ function WebViewInternal(webviewNode) {
 
   this.beforeFirstNavigation = true;
   this.validPartitionId = true;
+  // Used to save some state upon deferred attachment.
+  // If <object> bindings is not available, we defer attachment.
+  // This state contains whether or not the attachment request was for
+  // newwindow.
+  this.deferredAttachState = null;
 
   // on* Event handlers.
   this.on = {};
@@ -494,7 +501,25 @@ WebViewInternal.prototype.handleWebviewAttributeMutation =
  * @private
  */
 WebViewInternal.prototype.handleBrowserPluginAttributeMutation =
-    function(name, newValue) {
+    function(name, oldValue, newValue) {
+  if (name == 'internalbindings' && !oldValue && newValue) {
+    this.browserPluginNode.removeAttribute('internalbindings');
+
+    if (this.deferredAttachState) {
+      var self = this;
+      // A setTimeout is necessary for the binding to be initialized properly.
+      window.setTimeout(function() {
+        if (self.hasBindings()) {
+          var params = self.buildAttachParams(
+              self.deferredAttachState.isNewWindow);
+          self.browserPluginNode[PLUGIN_METHOD_ATTACH](self.instanceId, params);
+          self.deferredAttachState = null;
+        }
+      }, 0);
+    }
+    return;
+  }
+
   // This observer monitors mutations to attributes of the BrowserPlugin and
   // updates the <webview> attributes accordingly.
   // |newValue| is null if the attribute |name| has been removed.
@@ -570,6 +595,12 @@ WebViewInternal.prototype.onSizeChanged = function(newWidth, newHeight) {
   }
 };
 
+// Returns true if Browser Plugin bindings is available.
+// Bindings are unavailable if <object> is not in the render tree.
+WebViewInternal.prototype.hasBindings = function() {
+  return 'function' == typeof this.browserPluginNode[PLUGIN_METHOD_ATTACH];
+};
+
 WebViewInternal.prototype.hasNavigated = function() {
   return !this.beforeFirstNavigation;
 };
@@ -616,10 +647,9 @@ WebViewInternal.prototype.allocateInstanceId = function() {
   var self = this;
   GuestViewInternal.allocateInstanceId(
       function(instanceId) {
-        self.instanceId = instanceId;
         // TODO(lazyboy): Make sure this.autoNavigate_ stuff correctly updated
         // |self.src| at this point.
-        self.attachWindowAndSetUpEvents(self.instanceId, self.src);
+        self.attachWindow(instanceId, false);
       });
 };
 
@@ -704,25 +734,34 @@ WebViewInternal.prototype.setUserAgentOverride = function(userAgentOverride) {
   WebView.overrideUserAgent(this.instanceId, userAgentOverride);
 };
 
-/** @private */
-WebViewInternal.prototype.attachWindowAndSetUpEvents = function(
-    instanceId, opt_src, opt_partitionId) {
-  this.instanceId = instanceId;
-  // If we have a partition from the opener, use that instead.
-  var storagePartitionId =
-      opt_partitionId ||
-      this.webviewNode.getAttribute(WEB_VIEW_ATTRIBUTE_PARTITION) ||
-      this.webviewNode[WEB_VIEW_ATTRIBUTE_PARTITION];
+WebViewInternal.prototype.buildAttachParams = function(isNewWindow) {
   var params = {
     'api': 'webview',
     'instanceId': this.viewInstanceId,
     'name': this.name,
-    'src': opt_src,
-    'storagePartitionId': storagePartitionId,
+    // We don't need to navigate new window from here.
+    'src': isNewWindow ? undefined : this.src,
+    // If we have a partition from the opener, that will also be already
+    // set via this.onAttach().
+    'storagePartitionId': this.partition.toAttribute(),
     'userAgentOverride': this.userAgentOverride
   };
+  return params;
+};
+
+WebViewInternal.prototype.attachWindow = function(instanceId, isNewWindow) {
+  this.instanceId = instanceId;
+  var params = this.buildAttachParams(isNewWindow);
+
+  if (!this.hasBindings()) {
+    // No bindings means that the plugin isn't there (display: none), we defer
+    // attachWindow in this case.
+    this.deferredAttachState = {isNewWindow: isNewWindow};
+    return false;
+  }
 
-  return this.browserPluginNode['-internal-attach'](this.instanceId, params);
+  this.deferredAttachState = null;
+  return this.browserPluginNode[PLUGIN_METHOD_ATTACH](this.instanceId, params);
 };
 
 // Registers browser plugin <object> custom element.
@@ -741,7 +780,7 @@ function registerBrowserPluginElement() {
     if (!internal) {
       return;
     }
-    internal.handleBrowserPluginAttributeMutation(name, newValue);
+    internal.handleBrowserPluginAttributeMutation(name, oldValue, newValue);
   };
 
   proto.attachedCallback = function() {