Index: chrome/renderer/resources/extensions/browser_tag.js |
diff --git a/chrome/renderer/resources/extensions/browser_tag.js b/chrome/renderer/resources/extensions/browser_tag.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d65cf12a89bbf25ea29662341aeb737f49495d29 |
--- /dev/null |
+++ b/chrome/renderer/resources/extensions/browser_tag.js |
@@ -0,0 +1,91 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+// Shim that simulates a <browser> tag via Mutation Observers and the trick |
+// documented at http://ajaxian.com/archives/web-ninja-interview-erik-arvidsson |
+// to subclass HTML elements. |
+// |
+// The actual tag is implemented via the browser plugin. The internals of this |
+// are hidden via Shadow DOM. |
+ |
+var BROWSER_TAG_ATTRIBUTES = ['src', 'width', 'height']; |
arv (Not doing code reviews)
2012/06/25 21:02:24
You might want to wrap all of this code in a closu
Mihai Parparita -not on Chrome
2012/06/26 00:58:24
The extension module system does this already: htt
|
+ |
+// Handle <browser> tags already in the document. |
+window.addEventListener('DOMContentLoaded', function() { |
+ var browserNodes = document.body.getElementsByTagName('browser'); |
arv (Not doing code reviews)
2012/06/25 21:02:24
querySelectorAll is better here. getElementsByTagN
Mihai Parparita -not on Chrome
2012/06/26 00:58:24
Done.
|
+ for (var i = 0, browserNode; browserNode = browserNodes[i]; i++) { |
+ BrowserTag.decorate(browserNode); |
+ } |
+}); |
+ |
+// Handle <browser> tags added later. |
+var observer = new WebKitMutationObserver(function(mutations) { |
+ mutations.forEach(function(mutation) { |
+ for (var i = 0, addedNode; addedNode = mutation.addedNodes[i]; i++) { |
+ if (addedNode.tagName == 'BROWSER') { |
+ BrowserTag.decorate(addedNode); |
+ } |
+ } |
+ }); |
+}); |
+observer.observe(document, {subtree: true, childList: true}); |
+ |
+/** |
+ * @constructor |
+ */ |
+function BrowserTag() { |
+ return BrowserTag.decorate(document.createElement('browser')); |
+} |
+ |
+/** |
+ * @param {Node} node |
+ */ |
+BrowserTag.decorate = function(node) { |
+ // Make sure we don't decorate twice. |
+ if (node instanceof BrowserTag) { |
+ return; |
+ } |
+ node.__proto__ = BrowserTag.prototype; |
+ node.decorate_(); |
+} |
+ |
+BrowserTag.prototype.__proto__ = HTMLElement.prototype; |
+ |
+var decorate = function() { |
arv (Not doing code reviews)
2012/06/25 21:02:24
function decorate() {
|
+ this.shadowRoot_ = new WebKitShadowRoot(this); |
+ |
+ this.objectNode_ = document.createElement('object'); |
arv (Not doing code reviews)
2012/06/25 21:02:24
How about making objectNode_ non enumerable?
Mayb
Mihai Parparita -not on Chrome
2012/06/26 00:58:24
I decided that making BrowserTag into an HTML elem
|
+ this.objectNode_.setAttribute('type', 'application/browser-plugin'); |
arv (Not doing code reviews)
2012/06/25 21:02:24
.type = ...
Mihai Parparita -not on Chrome
2012/06/26 00:58:24
Done.
|
+ BROWSER_TAG_ATTRIBUTES.forEach(this.copyAttribute_, this); |
+ this.shadowRoot_.appendChild(this.objectNode_); |
+ |
+ var handleMutation = this.handleMutation_.bind(this); |
+ this.observer_ = new WebKitMutationObserver(function(mutations) { |
+ mutations.forEach(handleMutation); |
arv (Not doing code reviews)
2012/06/25 21:02:24
-4 indent
Mihai Parparita -not on Chrome
2012/06/26 00:58:24
Done.
|
+ }); |
+ this.observer_.observe( |
+ this, |
+ {attributes: true, attributeFilter: BROWSER_TAG_ATTRIBUTES}); |
+}; |
+Object.defineProperty(BrowserTag.prototype, 'decorate_', {value: decorate}); |
arv (Not doing code reviews)
2012/06/25 21:02:24
I feel like we could probably make this truly tran
|
+ |
+var handleMutation = function() { |
arv (Not doing code reviews)
2012/06/25 21:02:24
function handleMutation() {
|
+ switch (mutation.attributeName) { |
+ case 'src': |
+ this.objectNode_.postMessage(this.getAttribute('src')); |
arv (Not doing code reviews)
2012/06/25 21:02:24
You should also add accessors for src, width and h
Mihai Parparita -not on Chrome
2012/06/26 00:58:24
Done.
|
+ break; |
+ default: |
+ this.copyAttribute_(mutation.attributeName); |
+ break; |
+ } |
+}; |
+Object.defineProperty( |
+ BrowserTag.prototype, 'handleMutation_', {value: handleMutation}); |
+ |
+var copyAttribute = function(attributeName) { |
+ this.objectNode_.setAttribute( |
+ attributeName, this.getAttribute(attributeName)); |
+} |
+Object.defineProperty( |
+ BrowserTag.prototype, 'copyAttribute_', {value: copyAttribute}); |