Fix breakages in https://codereview.chromium.org/1155713003/
[chromium-blink-merge.git] / ios / web / web_state / js / resources / plugin_placeholder.js
blob4a588fdbeaf4f5d20659444a330ad55382e66c35
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.
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.
10 /**
11  * Namespace for this file. It depends on |__gCrWeb| having already been
12  * injected.
13  */
14 __gCrWeb['plugin'] = {};
16 /* Beginning of anonymous object. */
17 new function() {
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==';
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   };
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     }
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     }
94     return {
95       'width': width,
96       'height': height
97     };
98   };
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   };
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       }
138       var pluginSize = __gCrWeb['plugin'].getPluginSize_(plugin);
139       var widthStyle = pluginSize.width + 'px';
140       var heightStyle = pluginSize.height + 'px';
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';
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);
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);
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);
196       plugin.insertBefore(placeholder, plugin.firstChild);
197     }
198   };
199 }  // End of anonymous object