OLD | NEW |
(Empty) | |
| 1 // Copyright 2013 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 // This file adheres to closure-compiler conventions in order to enable |
| 6 // compilation with ADVANCED_OPTIMIZATIONS. See http://goo.gl/FwOgy |
| 7 // |
| 8 // Installs and runs the plugin placeholder function on the |__gCrWeb| object. |
| 9 |
| 10 /** |
| 11 * Namespace for this file. It depends on |__gCrWeb| having already been |
| 12 * injected. |
| 13 */ |
| 14 __gCrWeb['plugin'] = {}; |
| 15 |
| 16 /* Beginning of anonymous object. */ |
| 17 new function() { |
| 18 |
| 19 /* Data-URL version of plugin_blocked_android.png. Served this way rather |
| 20 * than with an intercepted URL to avoid messing up https pages. |
| 21 */ |
| 22 __gCrWeb['plugin'].imageData_ = |
| 23 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAQAAABLCVATAAAD' + |
| 24 'aklEQVR4Xn2Wz2tcVRTHP/e+O28mMxONJKlF4kIkP4luXFgQuuxCBaG41IWrLupOXLur+A' + |
| 25 'e4cmV3LiS6qujSLgq2CIKQUqS2YnWsRkzGSTIz7zyHw+EdchnkcOd+7+OeT84578tMwmet' + |
| 26 'O1fkar1RRNAgUJuqbeEn/0RUcdS6UX7w0X54/93qw4V+m0IReBiizhAYpG52kfrO86+F9/' + |
| 27 'YXNnukHOTpc5SHgpiOu1cT623FBELeGvgTXfppOAjN3dCKm7GIkWiY4LsBnqBPpGqAgN/z' + |
| 28 'CDMMBsCWX+pwibd5hzdZZmLNOsxDm8VAzIkt1hX5NLucqgrZm3RlIC/XscKTNlAQpvncMi' + |
| 29 'tAnEM33D4nqgbcosBSPT3DRTJ3+Cx+4UfV3/CQniMQQ5g2WMJkoGKHNodUCBDpsYEQ2KGm' + |
| 30 'JBKIFPT4nYckB9ueaPxRscamWczco3qXLcR9wx4ndBsziqFSjaOCAWLm4kj0xhhSMVFli4' + |
| 31 'opyYuLlJ7s+/xTE6IgcVBthUuW6goHZDiA5IeCAnFEhkKVxxQh+pnoqSeMCEw4Uvt5kEHP' + |
| 32 'c8IyF3iJ5De1NYSAMOYvOtxgwBqv0wcE5rR4gcQGq9Sc5wt7bq2JtfYtI0Ys8mCmLhFg7q' + |
| 33 'w6XKRStUHJiMJmpC8vglqypAOU/MwRiw7KYGKqxZSKqE/iTKrQAwGxv5oU4ZbzGHCTf1QN' + |
| 34 'OTXbQhJ/gbxKjy85IPECHQSQ3EFUfM0+93iZgluM6LuzDUTJOXpc5jcWeDb3DjQrsMhj9t' + |
| 35 'TdPcAq8mtjjunyFEtN8ohfOWaVZR88Qd2WKK15a5zoRY8ZmRaNIZ/yCZ/P1u0zY+9TASjc' + |
| 36 'q04YMzBhqAAUBXf5iWcITGdql3aTtpIZVnxGYvSxj1VPXUB0EtHnxBoT6iwgeXEwQfwC69' + |
| 37 'xmROAcr5DwESxa3XLGW9G9AgPGVKahzzb/UvEcq81PwCl/MyDMrUgxQeMH7tNniQW6nPKA' + |
| 38 'e5TU3KUFjPmTRxyofUsFeFVQqyENBHDAYyodJhR0CFrnfaYECgvAjdogEwZCVySQaJ8Zeq' + |
| 39 'AL874rsy+2ofT1ev5fkSdmihwF0jpOra/kskTHkGMckkG9Gg7Xvw9XtifXOy/GEgCr7H/r' + |
| 40 'yepFOFy5fu1agI9XH71RbRWRrDmHOhrfLYrx9ndv3Wz98R+P7LgG2uyMvgAAAABJRU5Erk' + |
| 41 'Jggg=='; |
| 42 |
| 43 /** |
| 44 * Returns the first <embed> child of the given node, if any. |
| 45 * @param {HTMLElement} node The node to check. |
| 46 * @return {HTMLElement} The first <embed> child, or null. |
| 47 * @private |
| 48 */ |
| 49 __gCrWeb['plugin'].getEmbedChild_ = function(node) { |
| 50 if (node.hasChildNodes()) { |
| 51 for (var i = 0; i < node.childNodes.length; i++) { |
| 52 if (node.childNodes[i].nodeName === 'EMBED') { |
| 53 return node.childNodes[i]; |
| 54 } |
| 55 } |
| 56 } |
| 57 return null; |
| 58 }; |
| 59 |
| 60 /** |
| 61 * Returns the size for the given plugin element. For the common |
| 62 * pattern of an IE-specific <object> wrapping an all-other-browsers <embed>, |
| 63 * the object doesn't have real style info (most notably size), so this uses |
| 64 * the embed in that case. |
| 65 * @param {HTMLElement} plugin The <object> node to check. |
| 66 * @return {Object} The size (width and height) for the plugin element. |
| 67 * @private |
| 68 */ |
| 69 __gCrWeb['plugin'].getPluginSize_ = function(plugin) { |
| 70 var style; |
| 71 // For the common pattern of an IE-specific <object> wrapping an |
| 72 // all-other-browsers <embed>, the object doesn't have real style info |
| 73 // (most notably size), so this uses the embed in that case. |
| 74 var embedChild = __gCrWeb['plugin'].getEmbedChild_(plugin); |
| 75 if (embedChild) { |
| 76 style = window.getComputedStyle(embedChild); |
| 77 } else { |
| 78 style = window.getComputedStyle(plugin); |
| 79 } |
| 80 |
| 81 var width = parseFloat(style.width); |
| 82 var height = parseFloat(style.height); |
| 83 if (plugin.tagName === 'APPLET') { |
| 84 // Size computation doesn't always work correctly with applets in |
| 85 // UIWebView, so use the attributes as fallbacks. |
| 86 if (isNaN(width)) { |
| 87 width = parseFloat(plugin.width); |
| 88 } |
| 89 if (isNaN(height)) { |
| 90 height = parseFloat(plugin.height); |
| 91 } |
| 92 } |
| 93 |
| 94 return { |
| 95 'width': width, |
| 96 'height': height |
| 97 }; |
| 98 }; |
| 99 |
| 100 /** |
| 101 * Checks whether an element is "significant". Whether a plugin is |
| 102 * "significant" is a heuristic that attempts to determine if it's a critical |
| 103 * visual element for the page (i.e., not invisible, or an incidental ad). |
| 104 * @param {HTMLElement} plugin The <object> node to check. |
| 105 * @return {Boolean} Whether the node is significant. |
| 106 * @private |
| 107 */ |
| 108 __gCrWeb['plugin'].isSignificantPlugin_ = function(plugin) { |
| 109 var windowWidth = window.innerWidth; |
| 110 var windowHeight = window.innerHeight; |
| 111 var pluginSize = __gCrWeb['plugin'].getPluginSize_(plugin); |
| 112 var pluginWidth = parseFloat(pluginSize.width); |
| 113 var pluginHeight = parseFloat(pluginSize.height); |
| 114 // A plugin must be at least |significantFraction| of one dimension of the |
| 115 // page, and a minimum size in the other dimension (to weed out banners and |
| 116 // tall side ads). |
| 117 var minSize = Math.min(200, windowWidth / 2, windowHeight / 2); |
| 118 var significantFraction = 0.5; |
| 119 return (pluginWidth > windowWidth * significantFraction && |
| 120 pluginHeight > minSize) || |
| 121 (pluginHeight > windowHeight * significantFraction && |
| 122 pluginWidth > minSize); |
| 123 }; |
| 124 |
| 125 /** |
| 126 * Walks the list of detected plugin elements, adding a placeholder to any |
| 127 * that are "significant" (see above). |
| 128 * @param {string} message The message to show in the placeholder. |
| 129 */ |
| 130 __gCrWeb['plugin']['addPluginPlaceholders'] = function(message) { |
| 131 var plugins = __gCrWeb['placeholderTargetPlugins']; |
| 132 for (i = 0; i < plugins.length; i++) { |
| 133 var plugin = plugins[i]; |
| 134 if (!__gCrWeb['plugin'].isSignificantPlugin_(plugin)) { |
| 135 continue; |
| 136 } |
| 137 |
| 138 var pluginSize = __gCrWeb['plugin'].getPluginSize_(plugin); |
| 139 var widthStyle = pluginSize.width + 'px'; |
| 140 var heightStyle = pluginSize.height + 'px'; |
| 141 |
| 142 // The outer wrapper is a div with relative positioning, as an anchor for |
| 143 // an inner absolute-position element, whose height is based on whether or |
| 144 // not there's an embed. If there is, then it's zero height, to avoid |
| 145 // affecting the layout of the (presumably-full-size) <embed> fallback. If |
| 146 // not, it's full-height to ensure the placeholder takes up the right |
| 147 // amount of space in the page layout. Width is full-width either way, to |
| 148 // avoid being affected by container alignment. |
| 149 var placeholder = document.createElement('div'); |
| 150 placeholder.style.width = widthStyle; |
| 151 if (__gCrWeb['plugin'].getEmbedChild_(plugin)) { |
| 152 placeholder.style.height = '0'; |
| 153 } else { |
| 154 placeholder.style.height = heightStyle; |
| 155 } |
| 156 placeholder.style.position = 'relative'; |
| 157 |
| 158 // Inside is a full-plugin-size solid box. |
| 159 var placeholderBox = document.createElement('div'); |
| 160 placeholderBox.style.position = 'absolute'; |
| 161 placeholderBox.style.boxSizing = 'border-box'; |
| 162 placeholderBox.style.width = widthStyle; |
| 163 placeholderBox.style.height = heightStyle; |
| 164 placeholderBox.style.border = '1px solid black'; |
| 165 placeholderBox.style.backgroundColor = '#808080'; |
| 166 placeholder.appendChild(placeholderBox); |
| 167 |
| 168 // Inside that is the plugin placeholder image, centered. |
| 169 var pluginImg = document.createElement('img'); |
| 170 var imageSize = 36; |
| 171 pluginImg.width = imageSize; |
| 172 pluginImg.height = imageSize; |
| 173 pluginImg.style.position = 'absolute'; |
| 174 // Center vertically and horizontally. |
| 175 var halfSize = imageSize / 2; |
| 176 pluginImg.style.top = '50%'; |
| 177 pluginImg.style.marginTop = '-' + halfSize + 'px'; |
| 178 pluginImg.style.left = '50%'; |
| 179 pluginImg.style.marginLeft = '-' + halfSize + 'px'; |
| 180 pluginImg.src = __gCrWeb['plugin'].imageData_; |
| 181 placeholderBox.appendChild(pluginImg); |
| 182 |
| 183 // And below that, the message. |
| 184 var label = document.createElement('p'); |
| 185 label.style.width = widthStyle; |
| 186 label.style.height = '1.5em'; |
| 187 label.style.position = 'absolute'; |
| 188 // Position below the image. |
| 189 label.style.top = '50%'; |
| 190 label.style.marginTop = imageSize + 'px'; |
| 191 // Center horizontally. |
| 192 label.style.textAlign = 'center'; |
| 193 label.textContent = message; |
| 194 placeholderBox.appendChild(label); |
| 195 |
| 196 plugin.insertBefore(placeholder, plugin.firstChild); |
| 197 } |
| 198 }; |
| 199 } // End of anonymous object |
OLD | NEW |