Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: chrome/renderer/plugins/chrome_plugin_placeholder.cc

Issue 23606022: Move renderer plugin code into a new component. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Move renderer plugin code into a new component - reply to comments and add namespace Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 #include "chrome/renderer/plugins/plugin_placeholder.h" 5 #include "chrome/renderer/plugins/chrome_plugin_placeholder.h"
6 6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/json/string_escape.h"
10 #include "base/strings/string_piece.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h" 7 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h" 8 #include "base/values.h"
14 #include "chrome/common/prerender_messages.h" 9 #include "chrome/common/prerender_messages.h"
15 #include "chrome/common/render_messages.h" 10 #include "chrome/common/render_messages.h"
16 #include "chrome/renderer/chrome_content_renderer_client.h" 11 #include "chrome/renderer/chrome_content_renderer_client.h"
17 #include "chrome/renderer/custom_menu_commands.h" 12 #include "chrome/renderer/custom_menu_commands.h"
18 #include "chrome/renderer/plugins/plugin_uma.h" 13 #include "chrome/renderer/plugins/plugin_uma.h"
19 #include "content/public/common/content_constants.h"
20 #include "content/public/common/context_menu_params.h" 14 #include "content/public/common/context_menu_params.h"
21 #include "content/public/renderer/render_thread.h" 15 #include "content/public/renderer/render_thread.h"
22 #include "content/public/renderer/render_view.h" 16 #include "content/public/renderer/render_view.h"
23 #include "grit/generated_resources.h" 17 #include "grit/generated_resources.h"
24 #include "grit/renderer_resources.h" 18 #include "grit/renderer_resources.h"
25 #include "grit/webkit_strings.h" 19 #include "grit/webkit_strings.h"
26 #include "third_party/WebKit/public/platform/WebData.h"
27 #include "third_party/WebKit/public/platform/WebPoint.h"
28 #include "third_party/WebKit/public/platform/WebURLRequest.h"
29 #include "third_party/WebKit/public/platform/WebVector.h"
30 #include "third_party/WebKit/public/web/WebContextMenuData.h"
31 #include "third_party/WebKit/public/web/WebDocument.h" 20 #include "third_party/WebKit/public/web/WebDocument.h"
32 #include "third_party/WebKit/public/web/WebElement.h"
33 #include "third_party/WebKit/public/web/WebFrame.h" 21 #include "third_party/WebKit/public/web/WebFrame.h"
34 #include "third_party/WebKit/public/web/WebInputEvent.h" 22 #include "third_party/WebKit/public/web/WebInputEvent.h"
35 #include "third_party/WebKit/public/web/WebPluginContainer.h"
36 #include "third_party/WebKit/public/web/WebScriptSource.h" 23 #include "third_party/WebKit/public/web/WebScriptSource.h"
37 #include "third_party/WebKit/public/web/WebView.h"
38 #include "third_party/re2/re2/re2.h"
39 #include "ui/base/l10n/l10n_util.h" 24 #include "ui/base/l10n/l10n_util.h"
40 #include "ui/base/resource/resource_bundle.h" 25 #include "ui/base/resource/resource_bundle.h"
41 #include "ui/webui/jstemplate_builder.h" 26 #include "ui/webui/jstemplate_builder.h"
42 27
43 using content::RenderThread; 28 using content::RenderThread;
44 using content::RenderView; 29 using content::RenderView;
45 using WebKit::WebContextMenuData;
46 using WebKit::WebDocument; 30 using WebKit::WebDocument;
47 using WebKit::WebElement; 31 using WebKit::WebElement;
48 using WebKit::WebFrame; 32 using WebKit::WebFrame;
49 using WebKit::WebMouseEvent; 33 using WebKit::WebMouseEvent;
50 using WebKit::WebNode; 34 using WebKit::WebNode;
51 using WebKit::WebPlugin; 35 using WebKit::WebPlugin;
52 using WebKit::WebPluginContainer; 36 using WebKit::WebPluginContainer;
53 using WebKit::WebPluginParams; 37 using WebKit::WebPluginParams;
54 using WebKit::WebPoint;
55 using WebKit::WebScriptSource;
56 using WebKit::WebString;
57 using WebKit::WebURLRequest;
58 using WebKit::WebVector;
59 using webkit_glue::CppArgumentList; 38 using webkit_glue::CppArgumentList;
60 using webkit_glue::CppVariant; 39 using webkit_glue::CppVariant;
61 40
62 const char* const kPluginPlaceholderDataURL = 41 namespace {
42 const plugins::PluginPlaceholder* g_last_active_menu = NULL;
43 } // namespace
44
45 const char ChromePluginPlaceholder::kPluginPlaceholderDataURL[] =
63 "chrome://pluginplaceholderdata/"; 46 "chrome://pluginplaceholderdata/";
64 47
65 #if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN) 48 ChromePluginPlaceholder::ChromePluginPlaceholder(
66 // Strings we used to parse the youtube plugin url. 49 content::RenderView* render_view,
67 const char* const kSlashVSlash = "/v/"; 50 WebKit::WebFrame* frame,
68 const char* const kSlashESlash = "/e/"; 51 const WebKit::WebPluginParams& params,
52 const std::string& html_data,
53 const string16& title)
54 : plugins::PluginPlaceholder(render_view,
55 frame,
56 params,
57 html_data,
58 GURL(kPluginPlaceholderDataURL)),
59 status_(new ChromeViewHostMsg_GetPluginInfo_Status),
60 title_(title),
61 #if defined(ENABLE_PLUGIN_INSTALLATION)
62 placeholder_routing_id_(MSG_ROUTING_NONE),
69 #endif 63 #endif
64 has_host_(false),
65 context_menu_request_id_(0) {
66 RenderThread::Get()->AddObserver(this);
67 }
70 68
71 namespace { 69 ChromePluginPlaceholder::~ChromePluginPlaceholder() {
72 const PluginPlaceholder* g_last_active_menu = NULL; 70 #if defined(ENABLE_PLUGIN_INSTALLATION)
73 71 if (placeholder_routing_id_ == MSG_ROUTING_NONE)
74 #if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN) 72 return;
75 // Helper function to get the youtube id from plugin params for old style 73 RenderThread::Get()->RemoveRoute(placeholder_routing_id_);
76 // embedded youtube video. 74 if (has_host_) {
77 std::string GetYoutubeVideoId(const WebPluginParams& params) { 75 RenderThread::Get()->Send(new ChromeViewHostMsg_RemovePluginPlaceholderHost(
78 GURL url(params.url); 76 routing_id(), placeholder_routing_id_));
79 std::string video_id = url.path().substr(strlen(kSlashVSlash)); 77 }
80 78 #endif
81 // Extract just the video id 79 RenderThread::Get()->RemoveObserver(this);
82 size_t video_id_end = video_id.find('&'); 80 if (context_menu_request_id_)
83 if (video_id_end != std::string::npos) 81 render_view()->CancelContextMenu(context_menu_request_id_);
84 video_id = video_id.substr(0, video_id_end);
85 return video_id;
86 } 82 }
87 #endif
88 } // namespace
89 83
90 // static 84 // static
91 PluginPlaceholder* PluginPlaceholder::CreateMissingPlugin( 85 ChromePluginPlaceholder* ChromePluginPlaceholder::CreateMissingPlugin(
92 RenderView* render_view, 86 RenderView* render_view,
93 WebFrame* frame, 87 WebFrame* frame,
94 const WebPluginParams& params) { 88 const WebPluginParams& params) {
95 const base::StringPiece template_html( 89 const base::StringPiece template_html(
96 ResourceBundle::GetSharedInstance().GetRawDataResource( 90 ResourceBundle::GetSharedInstance().GetRawDataResource(
97 IDR_BLOCKED_PLUGIN_HTML)); 91 IDR_BLOCKED_PLUGIN_HTML));
98 92
99 base::DictionaryValue values; 93 base::DictionaryValue values;
100 #if defined(ENABLE_PLUGIN_INSTALLATION) 94 #if defined(ENABLE_PLUGIN_INSTALLATION)
101 values.SetString("message", l10n_util::GetStringUTF8(IDS_PLUGIN_SEARCHING)); 95 values.SetString("message", l10n_util::GetStringUTF8(IDS_PLUGIN_SEARCHING));
102 #else 96 #else
103 values.SetString("message", 97 values.SetString("message",
104 l10n_util::GetStringUTF8(IDS_PLUGIN_NOT_SUPPORTED)); 98 l10n_util::GetStringUTF8(IDS_PLUGIN_NOT_SUPPORTED));
105 #endif 99 #endif
106 100
107 std::string html_data = webui::GetI18nTemplateHtml(template_html, &values); 101 std::string html_data = webui::GetI18nTemplateHtml(template_html, &values);
108 102
109 // |missing_plugin| will destroy itself when its WebViewPlugin is going away. 103 // |missing_plugin| will destroy itself when its WebViewPlugin is going away.
110 PluginPlaceholder* missing_plugin = new PluginPlaceholder( 104 ChromePluginPlaceholder* missing_plugin = new ChromePluginPlaceholder(
111 render_view, frame, params, html_data, params.mimeType); 105 render_view, frame, params, html_data, params.mimeType);
112 missing_plugin->set_allow_loading(true); 106 missing_plugin->set_allow_loading(true);
113 #if defined(ENABLE_PLUGIN_INSTALLATION) 107 #if defined(ENABLE_PLUGIN_INSTALLATION)
114 RenderThread::Get()->Send(new ChromeViewHostMsg_FindMissingPlugin( 108 RenderThread::Get()->Send(
115 missing_plugin->routing_id(), missing_plugin->CreateRoutingId(), 109 new ChromeViewHostMsg_FindMissingPlugin(missing_plugin->routing_id(),
116 params.mimeType.utf8())); 110 missing_plugin->CreateRoutingId(),
111 params.mimeType.utf8()));
117 #endif 112 #endif
118 return missing_plugin; 113 return missing_plugin;
119 } 114 }
120 115
121 PluginPlaceholder* PluginPlaceholder::CreateErrorPlugin( 116 // static
117 ChromePluginPlaceholder* ChromePluginPlaceholder::CreateErrorPlugin(
122 RenderView* render_view, 118 RenderView* render_view,
123 const base::FilePath& file_path) { 119 const base::FilePath& file_path) {
124 base::DictionaryValue values; 120 base::DictionaryValue values;
125 values.SetString("message", 121 values.SetString("message",
126 l10n_util::GetStringUTF8(IDS_PLUGIN_INITIALIZATION_ERROR)); 122 l10n_util::GetStringUTF8(IDS_PLUGIN_INITIALIZATION_ERROR));
127 123
128 const base::StringPiece template_html( 124 const base::StringPiece template_html(
129 ResourceBundle::GetSharedInstance().GetRawDataResource( 125 ResourceBundle::GetSharedInstance().GetRawDataResource(
130 IDR_BLOCKED_PLUGIN_HTML)); 126 IDR_BLOCKED_PLUGIN_HTML));
131 std::string html_data = webui::GetI18nTemplateHtml(template_html, &values); 127 std::string html_data = webui::GetI18nTemplateHtml(template_html, &values);
132 128
133 WebPluginParams params; 129 WebPluginParams params;
134 // |missing_plugin| will destroy itself when its WebViewPlugin is going away. 130 // |missing_plugin| will destroy itself when its WebViewPlugin is going away.
135 PluginPlaceholder* plugin = new PluginPlaceholder( 131 ChromePluginPlaceholder* plugin = new ChromePluginPlaceholder(
136 render_view, NULL, params, html_data, params.mimeType); 132 render_view, NULL, params, html_data, params.mimeType);
137 133
138 RenderThread::Get()->Send( 134 RenderThread::Get()->Send(new ChromeViewHostMsg_CouldNotLoadPlugin(
139 new ChromeViewHostMsg_CouldNotLoadPlugin(plugin->routing_id(), 135 plugin->routing_id(), file_path));
140 file_path));
141 return plugin; 136 return plugin;
142 } 137 }
143 138
144 // static 139 // static
145 PluginPlaceholder* PluginPlaceholder::CreateBlockedPlugin( 140 ChromePluginPlaceholder* ChromePluginPlaceholder::CreateBlockedPlugin(
146 RenderView* render_view, 141 RenderView* render_view,
147 WebFrame* frame, 142 WebFrame* frame,
148 const WebPluginParams& params, 143 const WebPluginParams& params,
149 const content::WebPluginInfo& plugin, 144 const content::WebPluginInfo& plugin,
150 const std::string& identifier, 145 const std::string& identifier,
151 const string16& name, 146 const string16& name,
152 int template_id, 147 int template_id,
153 const string16& message) { 148 const string16& message) {
154 base::DictionaryValue values; 149 base::DictionaryValue values;
155 values.SetString("message", message); 150 values.SetString("message", message);
156 values.SetString("name", name); 151 values.SetString("name", name);
157 values.SetString("hide", l10n_util::GetStringUTF8(IDS_PLUGIN_HIDE)); 152 values.SetString("hide", l10n_util::GetStringUTF8(IDS_PLUGIN_HIDE));
158 153
159 const base::StringPiece template_html( 154 const base::StringPiece template_html(
160 ResourceBundle::GetSharedInstance().GetRawDataResource( 155 ResourceBundle::GetSharedInstance().GetRawDataResource(template_id));
161 template_id));
162 156
163 DCHECK(!template_html.empty()) << "unable to load template. ID: " 157 DCHECK(!template_html.empty()) << "unable to load template. ID: "
164 << template_id; 158 << template_id;
165 std::string html_data = webui::GetI18nTemplateHtml(template_html, &values); 159 std::string html_data = webui::GetI18nTemplateHtml(template_html, &values);
166 160
167 // |blocked_plugin| will destroy itself when its WebViewPlugin is going away. 161 // |blocked_plugin| will destroy itself when its WebViewPlugin is going away.
168 PluginPlaceholder* blocked_plugin = new PluginPlaceholder( 162 ChromePluginPlaceholder* blocked_plugin =
169 render_view, frame, params, html_data, name); 163 new ChromePluginPlaceholder(render_view, frame, params, html_data, name);
170 blocked_plugin->plugin_info_ = plugin; 164 blocked_plugin->SetPluginInfo(plugin);
171 blocked_plugin->identifier_ = identifier; 165 blocked_plugin->SetIdentifier(identifier);
172 return blocked_plugin; 166 return blocked_plugin;
173 } 167 }
174 168
175 #if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN) 169 void ChromePluginPlaceholder::SetStatus(
176 // static 170 const ChromeViewHostMsg_GetPluginInfo_Status& status) {
177 PluginPlaceholder* PluginPlaceholder::CreateMobileYoutubePlugin( 171 status_->value = status.value;
178 content::RenderView* render_view,
179 WebFrame* frame,
180 const WebPluginParams& params) {
181 const base::StringPiece template_html(
182 ResourceBundle::GetSharedInstance().GetRawDataResource(
183 IDR_MOBILE_YOUTUBE_PLUGIN_HTML));
184
185 base::DictionaryValue values;
186 values.SetString("video_id", GetYoutubeVideoId(params));
187 std::string html_data = webui::GetI18nTemplateHtml(template_html, &values);
188
189 // |youtube_plugin| will destroy itself when its WebViewPlugin is going away.
190 PluginPlaceholder* youtube_plugin = new PluginPlaceholder(
191 render_view, frame, params, html_data, params.mimeType);
192 return youtube_plugin;
193 }
194 #endif
195
196 PluginPlaceholder::PluginPlaceholder(content::RenderView* render_view,
197 WebFrame* frame,
198 const WebPluginParams& params,
199 const std::string& html_data,
200 const string16& title)
201 : content::RenderViewObserver(render_view),
202 frame_(frame),
203 plugin_params_(params),
204 plugin_(WebViewPlugin::Create(
205 this, render_view->GetWebkitPreferences(), html_data,
206 GURL(kPluginPlaceholderDataURL))),
207 title_(title),
208 status_(new ChromeViewHostMsg_GetPluginInfo_Status),
209 is_blocked_for_prerendering_(false),
210 allow_loading_(false),
211 #if defined(ENABLE_PLUGIN_INSTALLATION)
212 placeholder_routing_id_(MSG_ROUTING_NONE),
213 #endif
214 hidden_(false),
215 has_host_(false),
216 finished_loading_(false),
217 context_menu_request_id_(0) {
218 RenderThread::Get()->AddObserver(this);
219 }
220
221 PluginPlaceholder::~PluginPlaceholder() {
222 RenderThread::Get()->RemoveObserver(this);
223 if (context_menu_request_id_)
224 render_view()->CancelContextMenu(context_menu_request_id_);
225
226 #if defined(ENABLE_PLUGIN_INSTALLATION)
227 if (placeholder_routing_id_ == MSG_ROUTING_NONE)
228 return;
229 RenderThread::Get()->RemoveRoute(placeholder_routing_id_);
230 if (has_host_) {
231 RenderThread::Get()->Send(
232 new ChromeViewHostMsg_RemovePluginPlaceholderHost(
233 routing_id(), placeholder_routing_id_));
234 }
235 #endif
236 } 172 }
237 173
238 #if defined(ENABLE_PLUGIN_INSTALLATION) 174 #if defined(ENABLE_PLUGIN_INSTALLATION)
239 int32 PluginPlaceholder::CreateRoutingId() { 175 int32 ChromePluginPlaceholder::CreateRoutingId() {
240 placeholder_routing_id_ = RenderThread::Get()->GenerateRoutingID(); 176 placeholder_routing_id_ = RenderThread::Get()->GenerateRoutingID();
241 RenderThread::Get()->AddRoute(placeholder_routing_id_, this); 177 RenderThread::Get()->AddRoute(placeholder_routing_id_, this);
242 return placeholder_routing_id_; 178 return placeholder_routing_id_;
243 } 179 }
244 #endif 180 #endif
245 181
246 void PluginPlaceholder::SetStatus( 182 bool ChromePluginPlaceholder::OnMessageReceived(const IPC::Message& message) {
247 const ChromeViewHostMsg_GetPluginInfo_Status& status) {
248 status_->value = status.value;
249 }
250
251 void PluginPlaceholder::BindWebFrame(WebFrame* frame) {
252 BindToJavascript(frame, "plugin");
253 BindCallback("load", base::Bind(&PluginPlaceholder::LoadCallback,
254 base::Unretained(this)));
255 BindCallback("hide", base::Bind(&PluginPlaceholder::HideCallback,
256 base::Unretained(this)));
257 BindCallback("openAboutPlugins",
258 base::Bind(&PluginPlaceholder::OpenAboutPluginsCallback,
259 base::Unretained(this)));
260 BindCallback("didFinishLoading",
261 base::Bind(&PluginPlaceholder::DidFinishLoadingCallback,
262 base::Unretained(this)));
263 #if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN)
264 BindCallback("openYoutubeURL",
265 base::Bind(&PluginPlaceholder::OpenYoutubeUrlCallback,
266 base::Unretained(this)));
267 #endif
268 }
269
270 bool PluginPlaceholder::OnMessageReceived(const IPC::Message& message) {
271 #if defined(ENABLE_PLUGIN_INSTALLATION) 183 #if defined(ENABLE_PLUGIN_INSTALLATION)
272 bool handled = true; 184 bool handled = true;
273 IPC_BEGIN_MESSAGE_MAP(PluginPlaceholder, message) 185 IPC_BEGIN_MESSAGE_MAP(ChromePluginPlaceholder, message)
274 IPC_MESSAGE_HANDLER(ChromeViewMsg_FoundMissingPlugin, 186 IPC_MESSAGE_HANDLER(ChromeViewMsg_FoundMissingPlugin, OnFoundMissingPlugin)
275 OnFoundMissingPlugin) 187 IPC_MESSAGE_HANDLER(ChromeViewMsg_DidNotFindMissingPlugin,
276 IPC_MESSAGE_HANDLER(ChromeViewMsg_DidNotFindMissingPlugin, 188 OnDidNotFindMissingPlugin)
277 OnDidNotFindMissingPlugin) 189 IPC_MESSAGE_HANDLER(ChromeViewMsg_StartedDownloadingPlugin,
278 IPC_MESSAGE_HANDLER(ChromeViewMsg_StartedDownloadingPlugin, 190 OnStartedDownloadingPlugin)
279 OnStartedDownloadingPlugin) 191 IPC_MESSAGE_HANDLER(ChromeViewMsg_FinishedDownloadingPlugin,
280 IPC_MESSAGE_HANDLER(ChromeViewMsg_FinishedDownloadingPlugin, 192 OnFinishedDownloadingPlugin)
281 OnFinishedDownloadingPlugin) 193 IPC_MESSAGE_HANDLER(ChromeViewMsg_ErrorDownloadingPlugin,
282 IPC_MESSAGE_HANDLER(ChromeViewMsg_ErrorDownloadingPlugin, 194 OnErrorDownloadingPlugin)
283 OnErrorDownloadingPlugin) 195 IPC_MESSAGE_HANDLER(ChromeViewMsg_CancelledDownloadingPlugin,
284 IPC_MESSAGE_HANDLER(ChromeViewMsg_CancelledDownloadingPlugin, 196 OnCancelledDownloadingPlugin)
285 OnCancelledDownloadingPlugin) 197 IPC_MESSAGE_UNHANDLED(handled = false)
286 IPC_MESSAGE_UNHANDLED(handled = false)
287 IPC_END_MESSAGE_MAP() 198 IPC_END_MESSAGE_MAP()
288 199
289 if (handled) 200 if (handled)
290 return true; 201 return true;
291 #endif 202 #endif
292 203
293 // We don't swallow these messages because multiple blocked plugins have an 204 // We don't swallow these messages because multiple blocked plugins have an
294 // interest in them. 205 // interest in them.
295 IPC_BEGIN_MESSAGE_MAP(PluginPlaceholder, message) 206 IPC_BEGIN_MESSAGE_MAP(ChromePluginPlaceholder, message)
296 IPC_MESSAGE_HANDLER(ChromeViewMsg_LoadBlockedPlugins, OnLoadBlockedPlugins) 207 IPC_MESSAGE_HANDLER(ChromeViewMsg_LoadBlockedPlugins, OnLoadBlockedPlugins)
297 IPC_MESSAGE_HANDLER(PrerenderMsg_SetIsPrerendering, OnSetIsPrerendering) 208 IPC_MESSAGE_HANDLER(PrerenderMsg_SetIsPrerendering, OnSetIsPrerendering)
298 IPC_END_MESSAGE_MAP() 209 IPC_END_MESSAGE_MAP()
299 210
300 return false; 211 return false;
301 } 212 }
302 213
303 void PluginPlaceholder::ReplacePlugin(WebPlugin* new_plugin) { 214 void ChromePluginPlaceholder::OnLoadBlockedPlugins(
304 CHECK(plugin_); 215 const std::string& identifier) {
305 if (!new_plugin) { 216 plugins::PluginPlaceholder::OnLoadBlockedPlugins(identifier);
306 PluginUMAReporter::GetInstance()->ReportPluginMissing(
307 plugin_params_.mimeType.utf8(),
308 plugin_params_.url);
309 return;
310 }
311
312 WebPluginContainer* container = plugin_->container();
313 // Set the new plug-in on the container before initializing it.
314 container->setPlugin(new_plugin);
315 // Save the element in case the plug-in is removed from the page during
316 // initialization.
317 WebElement element = container->element();
318 if (!new_plugin->initialize(container)) {
319 // We couldn't initialize the new plug-in. Restore the old one and abort.
320 container->setPlugin(plugin_);
321 return;
322 }
323
324 // The plug-in has been removed from the page. Destroy the old plug-in
325 // (which will destroy us).
326 if (!element.pluginContainer()) {
327 plugin_->destroy();
328 return;
329 }
330
331 // During initialization, the new plug-in might have replaced itself in turn
332 // with another plug-in. Make sure not to use the passed in |new_plugin| after
333 // this point.
334 new_plugin = container->plugin();
335
336 plugin_->RestoreTitleText();
337 container->invalidate();
338 container->reportGeometry();
339 plugin_->ReplayReceivedData(new_plugin);
340 plugin_->destroy();
341 } 217 }
342 218
343 void PluginPlaceholder::HidePlugin() { 219 void ChromePluginPlaceholder::OpenAboutPluginsCallback(
344 hidden_ = true; 220 const CppArgumentList& args,
345 WebPluginContainer* container = plugin_->container(); 221 CppVariant* result) {
346 WebElement element = container->element(); 222 RenderThread::Get()->Send(
347 element.setAttribute("style", "display: none;"); 223 new ChromeViewHostMsg_OpenAboutPlugins(routing_id()));
348 // If we have a width and height, search for a parent (often <div>) with the
349 // same dimensions. If we find such a parent, hide that as well.
350 // This makes much more uncovered page content usable (including clickable)
351 // as opposed to merely visible.
352 // TODO(cevans) -- it's a foul heurisitc but we're going to tolerate it for
353 // now for these reasons:
354 // 1) Makes the user experience better.
355 // 2) Foulness is encapsulated within this single function.
356 // 3) Confidence in no fasle positives.
357 // 4) Seems to have a good / low false negative rate at this time.
358 if (element.hasAttribute("width") && element.hasAttribute("height")) {
359 std::string width_str("width:[\\s]*");
360 width_str += element.getAttribute("width").utf8().data();
361 if (EndsWith(width_str, "px", false)) {
362 width_str = width_str.substr(0, width_str.length() - 2);
363 }
364 TrimWhitespace(width_str, TRIM_TRAILING, &width_str);
365 width_str += "[\\s]*px";
366 std::string height_str("height:[\\s]*");
367 height_str += element.getAttribute("height").utf8().data();
368 if (EndsWith(height_str, "px", false)) {
369 height_str = height_str.substr(0, height_str.length() - 2);
370 }
371 TrimWhitespace(height_str, TRIM_TRAILING, &height_str);
372 height_str += "[\\s]*px";
373 WebNode parent = element;
374 while (!parent.parentNode().isNull()) {
375 parent = parent.parentNode();
376 if (!parent.isElementNode())
377 continue;
378 element = parent.toConst<WebElement>();
379 if (element.hasAttribute("style")) {
380 std::string style_str = element.getAttribute("style").utf8();
381 if (RE2::PartialMatch(style_str, width_str) &&
382 RE2::PartialMatch(style_str, height_str))
383 element.setAttribute("style", "display: none;");
384 }
385 }
386 }
387 } 224 }
388 225
389 void PluginPlaceholder::WillDestroyPlugin() { 226 void ChromePluginPlaceholder::OnSetIsPrerendering(bool is_prerendering) {
390 delete this; 227 plugins::PluginPlaceholder::OnSetIsPrerendering(is_prerendering);
391 } 228 }
392 229
393 #if defined(ENABLE_PLUGIN_INSTALLATION) 230 #if defined(ENABLE_PLUGIN_INSTALLATION)
394 void PluginPlaceholder::OnDidNotFindMissingPlugin() { 231 void ChromePluginPlaceholder::OnDidNotFindMissingPlugin() {
395 SetMessage(l10n_util::GetStringUTF16(IDS_PLUGIN_NOT_FOUND)); 232 SetMessage(l10n_util::GetStringUTF16(IDS_PLUGIN_NOT_FOUND));
396 } 233 }
397 234
398 void PluginPlaceholder::OnFoundMissingPlugin(const string16& plugin_name) { 235 void ChromePluginPlaceholder::OnFoundMissingPlugin(
236 const string16& plugin_name) {
399 if (status_->value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound) 237 if (status_->value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound)
400 SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_FOUND, plugin_name)); 238 SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_FOUND, plugin_name));
401 has_host_ = true; 239 has_host_ = true;
402 plugin_name_ = plugin_name; 240 plugin_name_ = plugin_name;
403 } 241 }
404 242
405 void PluginPlaceholder::OnStartedDownloadingPlugin() { 243 void ChromePluginPlaceholder::OnStartedDownloadingPlugin() {
406 SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING, plugin_name_)); 244 SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING, plugin_name_));
407 } 245 }
408 246
409 void PluginPlaceholder::OnFinishedDownloadingPlugin() { 247 void ChromePluginPlaceholder::OnFinishedDownloadingPlugin() {
410 bool is_installing = 248 bool is_installing =
411 status_->value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound; 249 status_->value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound;
412 SetMessage(l10n_util::GetStringFUTF16( 250 SetMessage(l10n_util::GetStringFUTF16(
413 is_installing ? IDS_PLUGIN_INSTALLING : IDS_PLUGIN_UPDATING, 251 is_installing ? IDS_PLUGIN_INSTALLING : IDS_PLUGIN_UPDATING,
414 plugin_name_)); 252 plugin_name_));
415 } 253 }
416 254
417 void PluginPlaceholder::OnErrorDownloadingPlugin(const std::string& error) { 255 void ChromePluginPlaceholder::OnErrorDownloadingPlugin(
256 const std::string& error) {
418 SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR, 257 SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR,
419 UTF8ToUTF16(error))); 258 UTF8ToUTF16(error)));
420 } 259 }
421 260
422 void PluginPlaceholder::OnCancelledDownloadingPlugin() { 261 void ChromePluginPlaceholder::OnCancelledDownloadingPlugin() {
423 SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_CANCELLED, 262 SetMessage(
424 plugin_name_)); 263 l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_CANCELLED, plugin_name_));
425 } 264 }
426 #endif // defined(ENABLE_PLUGIN_INSTALLATION) 265 #endif // defined(ENABLE_PLUGIN_INSTALLATION)
427 266
428 void PluginPlaceholder::PluginListChanged() { 267 void ChromePluginPlaceholder::PluginListChanged() {
429 if (!frame_) 268 if (!GetFrame())
430 return; 269 return;
431 WebDocument document = frame_->top()->document(); 270 WebDocument document = GetFrame()->top()->document();
432 if (document.isNull()) 271 if (document.isNull())
433 return; 272 return;
434 273
435 ChromeViewHostMsg_GetPluginInfo_Output output; 274 ChromeViewHostMsg_GetPluginInfo_Output output;
436 std::string mime_type(plugin_params_.mimeType.utf8()); 275 std::string mime_type(GetPluginParams().mimeType.utf8());
437 render_view()->Send(new ChromeViewHostMsg_GetPluginInfo( 276 render_view()->Send(
438 routing_id(), GURL(plugin_params_.url), document.url(), 277 new ChromeViewHostMsg_GetPluginInfo(routing_id(),
439 mime_type, &output)); 278 GURL(GetPluginParams().url),
279 document.url(),
280 mime_type,
281 &output));
440 if (output.status.value == status_->value) 282 if (output.status.value == status_->value)
441 return; 283 return;
442 WebPlugin* new_plugin = chrome::ChromeContentRendererClient::CreatePlugin( 284 WebPlugin* new_plugin = chrome::ChromeContentRendererClient::CreatePlugin(
443 render_view(), frame_, plugin_params_, output); 285 render_view(), GetFrame(), GetPluginParams(), output);
444 ReplacePlugin(new_plugin); 286 ReplacePlugin(new_plugin);
287 if (!new_plugin) {
288 PluginUMAReporter::GetInstance()->ReportPluginMissing(
289 GetPluginParams().mimeType.utf8(), GURL(GetPluginParams().url));
290 }
445 } 291 }
446 292
447 void PluginPlaceholder::OnMenuAction(int request_id, unsigned action) { 293 void ChromePluginPlaceholder::OnMenuAction(int request_id, unsigned action) {
448 DCHECK_EQ(context_menu_request_id_, request_id); 294 DCHECK_EQ(context_menu_request_id_, request_id);
449 if (g_last_active_menu != this) 295 if (g_last_active_menu != this)
450 return; 296 return;
451 switch (action) { 297 switch (action) {
452 case chrome::MENU_COMMAND_PLUGIN_RUN: { 298 case chrome::MENU_COMMAND_PLUGIN_RUN: {
453 RenderThread::Get()->RecordUserMetrics("Plugin_Load_Menu"); 299 RenderThread::Get()->RecordUserMetrics("Plugin_Load_Menu");
454 LoadPlugin(); 300 LoadPlugin();
455 break; 301 break;
456 } 302 }
457 case chrome::MENU_COMMAND_PLUGIN_HIDE: { 303 case chrome::MENU_COMMAND_PLUGIN_HIDE: {
458 RenderThread::Get()->RecordUserMetrics("Plugin_Hide_Menu"); 304 RenderThread::Get()->RecordUserMetrics("Plugin_Hide_Menu");
459 HidePlugin(); 305 HidePlugin();
460 break; 306 break;
461 } 307 }
462 default: 308 default:
463 NOTREACHED(); 309 NOTREACHED();
464 } 310 }
465 } 311 }
466 312
467 void PluginPlaceholder::OnMenuClosed(int request_id) { 313 void ChromePluginPlaceholder::OnMenuClosed(int request_id) {
468 DCHECK_EQ(context_menu_request_id_, request_id); 314 DCHECK_EQ(context_menu_request_id_, request_id);
469 context_menu_request_id_ = 0; 315 context_menu_request_id_ = 0;
470 } 316 }
471 317
472 void PluginPlaceholder::SetMessage(const string16& message) { 318 void ChromePluginPlaceholder::ShowContextMenu(const WebMouseEvent& event) {
473 message_ = message;
474 if (finished_loading_)
475 UpdateMessage();
476 }
477
478 void PluginPlaceholder::UpdateMessage() {
479 std::string script = "window.setMessage(" +
480 base::GetDoubleQuotedJson(message_) + ")";
481 plugin_->web_view()->mainFrame()->executeScript(
482 WebScriptSource(ASCIIToUTF16(script)));
483 }
484
485 void PluginPlaceholder::ShowContextMenu(const WebMouseEvent& event) {
486 if (context_menu_request_id_) 319 if (context_menu_request_id_)
487 return; // Don't allow nested context menu requests. 320 return; // Don't allow nested context menu requests.
488 321
489 content::ContextMenuParams params; 322 content::ContextMenuParams params;
490 323
491 content::MenuItem name_item; 324 content::MenuItem name_item;
492 name_item.label = title_; 325 name_item.label = title_;
493 params.custom_items.push_back(name_item); 326 params.custom_items.push_back(name_item);
494 327
495 content::MenuItem separator_item; 328 content::MenuItem separator_item;
496 separator_item.type = content::MenuItem::SEPARATOR; 329 separator_item.type = content::MenuItem::SEPARATOR;
497 params.custom_items.push_back(separator_item); 330 params.custom_items.push_back(separator_item);
498 331
499 if (!plugin_info_.path.value().empty()) { 332 if (!GetPluginInfo().path.value().empty()) {
500 content::MenuItem run_item; 333 content::MenuItem run_item;
501 run_item.action = chrome::MENU_COMMAND_PLUGIN_RUN; 334 run_item.action = chrome::MENU_COMMAND_PLUGIN_RUN;
502 // Disable this menu item if the plugin is blocked by policy. 335 // Disable this menu item if the plugin is blocked by policy.
503 run_item.enabled = allow_loading_; 336 run_item.enabled = LoadingAllowed();
504 run_item.label = l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PLUGIN_RUN); 337 run_item.label = l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PLUGIN_RUN);
505 params.custom_items.push_back(run_item); 338 params.custom_items.push_back(run_item);
506 } 339 }
507 340
508 content::MenuItem hide_item; 341 content::MenuItem hide_item;
509 hide_item.action = chrome::MENU_COMMAND_PLUGIN_HIDE; 342 hide_item.action = chrome::MENU_COMMAND_PLUGIN_HIDE;
510 hide_item.enabled = true; 343 hide_item.enabled = true;
511 hide_item.label = l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PLUGIN_HIDE); 344 hide_item.label = l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PLUGIN_HIDE);
512 params.custom_items.push_back(hide_item); 345 params.custom_items.push_back(hide_item);
513 346
514 params.x = event.windowX; 347 params.x = event.windowX;
515 params.y = event.windowY; 348 params.y = event.windowY;
516 349
517 context_menu_request_id_ = render_view()->ShowContextMenu(this, params); 350 context_menu_request_id_ = render_view()->ShowContextMenu(this, params);
518 g_last_active_menu = this; 351 g_last_active_menu = this;
519 } 352 }
520 353
521 void PluginPlaceholder::OnLoadBlockedPlugins(const std::string& identifier) { 354 void ChromePluginPlaceholder::BindWebFrame(WebKit::WebFrame* frame) {
522 if (!identifier.empty() && identifier != identifier_) 355 plugins::PluginPlaceholder::BindWebFrame(frame);
523 return; 356 BindCallback("openAboutPlugins",
524 357 base::Bind(&ChromePluginPlaceholder::OpenAboutPluginsCallback,
525 RenderThread::Get()->RecordUserMetrics("Plugin_Load_UI"); 358 base::Unretained(this)));
526 LoadPlugin();
527 } 359 }
528
529 void PluginPlaceholder::OnSetIsPrerendering(bool is_prerendering) {
530 // Prerendering can only be enabled prior to a RenderView's first navigation,
531 // so no BlockedPlugin should see the notification that enables prerendering.
532 DCHECK(!is_prerendering);
533 if (is_blocked_for_prerendering_ && !is_prerendering)
534 LoadPlugin();
535 }
536
537 void PluginPlaceholder::LoadPlugin() {
538 // This is not strictly necessary but is an important defense in case the
539 // event propagation changes between "close" vs. "click-to-play".
540 if (hidden_)
541 return;
542 if (!allow_loading_) {
543 NOTREACHED();
544 return;
545 }
546
547 // TODO(mmenke): In the case of prerendering, feed into
548 // ChromeContentRendererClient::CreatePlugin instead, to
549 // reduce the chance of future regressions.
550 WebPlugin* plugin =
551 render_view()->CreatePlugin(frame_, plugin_info_, plugin_params_);
552 ReplacePlugin(plugin);
553 }
554
555 void PluginPlaceholder::LoadCallback(const CppArgumentList& args,
556 CppVariant* result) {
557 RenderThread::Get()->RecordUserMetrics("Plugin_Load_Click");
558 LoadPlugin();
559 }
560
561 void PluginPlaceholder::HideCallback(const CppArgumentList& args,
562 CppVariant* result) {
563 RenderThread::Get()->RecordUserMetrics("Plugin_Hide_Click");
564 HidePlugin();
565 }
566
567 void PluginPlaceholder::OpenAboutPluginsCallback(const CppArgumentList& args,
568 CppVariant* result) {
569 RenderThread::Get()->Send(
570 new ChromeViewHostMsg_OpenAboutPlugins(routing_id()));
571 }
572
573 void PluginPlaceholder::DidFinishLoadingCallback(const CppArgumentList& args,
574 CppVariant* result) {
575 finished_loading_ = true;
576 if (message_.length() > 0)
577 UpdateMessage();
578 }
579
580 #if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN)
581 void PluginPlaceholder::OpenYoutubeUrlCallback(const CppArgumentList& args,
582 CppVariant* result) {
583 std::string youtube("vnd.youtube:");
584 GURL url(youtube.append(GetYoutubeVideoId(plugin_params_)));
585 WebURLRequest request;
586 request.initialize();
587 request.setURL(url);
588 render_view()->LoadURLExternally(
589 frame_, request, WebKit::WebNavigationPolicyNewForegroundTab);
590 }
591
592 bool PluginPlaceholder::IsValidYouTubeVideo(const std::string& path) {
593 unsigned len = strlen(kSlashVSlash);
594
595 // check for more than just /v/ or /e/.
596 if (path.length() <= len)
597 return false;
598
599 std::string str = StringToLowerASCII(path);
600 // Youtube flash url can start with /v/ or /e/.
601 if (strncmp(str.data(), kSlashVSlash, len) != 0 &&
602 strncmp(str.data(), kSlashESlash, len) != 0)
603 return false;
604
605 // Start after /v/
606 for (unsigned i = len; i < path.length(); i++) {
607 char c = str[i];
608 if (isalpha(c) || isdigit(c) || c == '_' || c == '-')
609 continue;
610 // The url can have more parameters such as &hl=en after the video id.
611 // Once we start seeing extra parameters we can return true.
612 return c == '&' && i > len;
613 }
614 return true;
615 }
616
617 bool PluginPlaceholder::IsYouTubeURL(const GURL& url,
618 const std::string& mime_type) {
619 std::string host = url.host();
620 bool is_youtube = EndsWith(host, "youtube.com", true) ||
621 EndsWith(host, "youtube-nocookie.com", true);
622
623 return is_youtube && IsValidYouTubeVideo(url.path()) &&
624 LowerCaseEqualsASCII(mime_type, content::kFlashPluginSwfMimeType);
625 }
626 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698