OLD | NEW |
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 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 "webkit/default_plugin/plugin_impl_win.h" | 5 #include "webkit/default_plugin/plugin_impl_win.h" |
6 | 6 |
7 #include <shellapi.h> | 7 #include <shellapi.h> |
8 | 8 |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/path_service.h" | 10 #include "base/path_service.h" |
11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
12 #include "googleurl/src/gurl.h" | 12 #include "googleurl/src/gurl.h" |
13 #include "grit/webkit_strings.h" | 13 #include "grit/webkit_strings.h" |
14 #include "unicode/locid.h" | 14 #include "unicode/locid.h" |
15 #include "webkit/default_plugin/activex_installer.h" | |
16 #include "webkit/activex_shim/activex_shared.h" | |
17 #include "webkit/activex_shim/npn_scripting.h" | |
18 #include "webkit/default_plugin/default_plugin_shared.h" | 15 #include "webkit/default_plugin/default_plugin_shared.h" |
19 #include "webkit/default_plugin/plugin_main.h" | 16 #include "webkit/default_plugin/plugin_main.h" |
20 #include "webkit/glue/webkit_glue.h" | 17 #include "webkit/glue/webkit_glue.h" |
21 | 18 |
22 static const int TOOLTIP_MAX_WIDTH = 500; | 19 static const int TOOLTIP_MAX_WIDTH = 500; |
23 | 20 |
24 PluginInstallerImpl::PluginInstallerImpl(int16 mode) | 21 PluginInstallerImpl::PluginInstallerImpl(int16 mode) |
25 : instance_(NULL), | 22 : instance_(NULL), |
26 is_activex_(false), | |
27 mode_(mode), | 23 mode_(mode), |
28 plugin_install_stream_(NULL), | 24 plugin_install_stream_(NULL), |
29 plugin_installer_state_(PluginInstallerStateUndefined), | 25 plugin_installer_state_(PluginInstallerStateUndefined), |
30 install_dialog_(NULL), | 26 install_dialog_(NULL), |
31 enable_click_(false), | 27 enable_click_(false), |
32 icon_(NULL), | 28 icon_(NULL), |
33 bold_font_(NULL), | 29 bold_font_(NULL), |
34 regular_font_(NULL), | 30 regular_font_(NULL), |
35 underline_font_(NULL), | 31 underline_font_(NULL), |
36 tooltip_(NULL), | 32 tooltip_(NULL), |
37 activex_installer_(NULL), | |
38 installation_job_monitor_thread_( | 33 installation_job_monitor_thread_( |
39 new PluginInstallationJobMonitorThread()), | 34 new PluginInstallationJobMonitorThread()), |
40 plugin_database_handler_(*this), | 35 plugin_database_handler_(*this), |
41 plugin_download_url_for_display_(false) { | 36 plugin_download_url_for_display_(false) { |
42 } | 37 } |
43 | 38 |
44 PluginInstallerImpl::~PluginInstallerImpl() { | 39 PluginInstallerImpl::~PluginInstallerImpl() { |
45 installation_job_monitor_thread_->Stop(); | 40 installation_job_monitor_thread_->Stop(); |
46 | 41 |
47 if (bold_font_) | 42 if (bold_font_) |
48 DeleteObject(bold_font_); | 43 DeleteObject(bold_font_); |
49 | 44 |
50 if (underline_font_) | 45 if (underline_font_) |
51 DeleteObject(underline_font_); | 46 DeleteObject(underline_font_); |
52 | 47 |
53 if (activex_installer_) { | |
54 activex_installer_->Cleanup(); | |
55 activex_installer_->Release(); | |
56 } | |
57 | |
58 if (tooltip_) | 48 if (tooltip_) |
59 DestroyWindow(tooltip_); | 49 DestroyWindow(tooltip_); |
60 } | 50 } |
61 | 51 |
62 bool PluginInstallerImpl::Initialize(HINSTANCE module_handle, NPP instance, | 52 bool PluginInstallerImpl::Initialize(HINSTANCE module_handle, NPP instance, |
63 NPMIMEType mime_type, int16 argc, | 53 NPMIMEType mime_type, int16 argc, |
64 char* argn[], char* argv[]) { | 54 char* argn[], char* argv[]) { |
65 DLOG(INFO) << __FUNCTION__ << " Mime Type : " << mime_type; | 55 DLOG(INFO) << __FUNCTION__ << " Mime Type : " << mime_type; |
66 DCHECK(instance != NULL); | 56 DCHECK(instance != NULL); |
67 DCHECK(module_handle != NULL); | 57 DCHECK(module_handle != NULL); |
68 | 58 |
| 59 if (mime_type == NULL || strlen(mime_type) == 0) { |
| 60 DLOG(WARNING) << __FUNCTION__ << " Invalid parameters passed in"; |
| 61 NOTREACHED(); |
| 62 return false; |
| 63 } |
| 64 |
69 instance_ = instance; | 65 instance_ = instance; |
70 mime_type_ = mime_type; | 66 mime_type_ = mime_type; |
71 | 67 |
72 // The clsid without the {} parentheses. | 68 if (!webkit_glue::GetPluginFinderURL(&plugin_finder_url_)) { |
73 std::string raw_activex_clsid; | |
74 if (!ParseInstantiationArguments(mime_type, instance, argc, argn, argv, | |
75 &raw_activex_clsid, &is_activex_, | |
76 &activex_clsid_, | |
77 &activex_codebase_, | |
78 &plugin_download_url_, | |
79 &plugin_finder_url_)) { | |
80 DLOG(ERROR) << "Incorrect arguments passed to plugin"; | |
81 NOTREACHED(); | 69 NOTREACHED(); |
| 70 DLOG(WARNING) << __FUNCTION__ << " Failed to get the plugin finder URL"; |
82 return false; | 71 return false; |
83 } | 72 } |
84 | 73 |
85 if (!installation_job_monitor_thread_->Initialize()) { | 74 if (!installation_job_monitor_thread_->Initialize()) { |
86 DLOG(ERROR) << "Failed to initialize plugin install job"; | 75 DLOG(ERROR) << "Failed to initialize plugin install job"; |
87 NOTREACHED(); | 76 NOTREACHED(); |
88 return false; | 77 return false; |
89 } | 78 } |
90 | 79 |
91 InitializeResources(module_handle); | 80 InitializeResources(module_handle); |
92 | 81 |
93 if (is_activex_) { | 82 DisplayStatus(IDS_DEFAULT_PLUGIN_GET_PLUGIN_MSG_NO_PLUGIN_NAME); |
94 // If the codebase is not from a whitelisted website, we do not allow | 83 plugin_database_handler_.DownloadPluginsFileIfNeeded(plugin_finder_url_); |
95 // download. | |
96 if (!activex_shim::IsCodebaseAllowed(raw_activex_clsid, | |
97 activex_codebase_)) { | |
98 activex_codebase_.clear(); | |
99 plugin_download_url_.clear(); | |
100 } | |
101 | |
102 if (!plugin_download_url_.empty()) { | |
103 set_plugin_installer_state(PluginListDownloaded); | |
104 DisplayAvailablePluginStatus(); | |
105 NotifyPluginStatus(default_plugin::MISSING_PLUGIN_AVAILABLE); | |
106 } else { | |
107 set_plugin_installer_state(PluginListDownloadFailed); | |
108 DisplayStatus(IDS_DEFAULT_PLUGIN_NO_PLUGIN_AVAILABLE_MSG); | |
109 } | |
110 } else { | |
111 DisplayStatus(IDS_DEFAULT_PLUGIN_GET_PLUGIN_MSG_NO_PLUGIN_NAME); | |
112 plugin_database_handler_.DownloadPluginsFileIfNeeded(plugin_finder_url_); | |
113 } | |
114 | 84 |
115 return true; | 85 return true; |
116 } | 86 } |
117 | 87 |
118 void PluginInstallerImpl::Shutdown() { | 88 void PluginInstallerImpl::Shutdown() { |
119 if (install_dialog_) { | 89 if (install_dialog_) { |
120 install_dialog_->RemoveInstaller(this); | 90 install_dialog_->RemoveInstaller(this); |
121 install_dialog_ = NULL; | 91 install_dialog_ = NULL; |
122 } | 92 } |
123 | 93 |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 DisplayAvailablePluginStatus(); | 251 DisplayAvailablePluginStatus(); |
282 NotifyPluginStatus(default_plugin::MISSING_PLUGIN_AVAILABLE); | 252 NotifyPluginStatus(default_plugin::MISSING_PLUGIN_AVAILABLE); |
283 } else { | 253 } else { |
284 DLOG(WARNING) << "No plugin available for mime type " << mime_type_; | 254 DLOG(WARNING) << "No plugin available for mime type " << mime_type_; |
285 DisplayStatus(IDS_DEFAULT_PLUGIN_NO_PLUGIN_AVAILABLE_MSG); | 255 DisplayStatus(IDS_DEFAULT_PLUGIN_NO_PLUGIN_AVAILABLE_MSG); |
286 } | 256 } |
287 } | 257 } |
288 } | 258 } |
289 | 259 |
290 int16 PluginInstallerImpl::NPP_HandleEvent(void* event) { | 260 int16 PluginInstallerImpl::NPP_HandleEvent(void* event) { |
291 // This is a hack. The renderer will send a direct custom message to ask for | |
292 // installation. | |
293 NPEvent* npp_event = static_cast<NPEvent*>(event); | 261 NPEvent* npp_event = static_cast<NPEvent*>(event); |
294 if (npp_event->event == kInstallMissingPluginMessage) { | 262 if (npp_event->event == kInstallMissingPluginMessage) { |
295 // We could get this message because InfoBar may not be in sync with our | 263 // We could get this message because InfoBar may not be in sync with our |
296 // internal processing. So we need to check the status. | 264 // internal processing. So we need to check the status. |
297 if (plugin_installer_state() == PluginListDownloaded) { | 265 if (plugin_installer_state() == PluginListDownloaded) { |
298 ShowInstallDialog(); | 266 ShowInstallDialog(); |
299 } | 267 } |
300 } | 268 } |
301 return 0; | 269 return 0; |
302 } | 270 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 } | 323 } |
356 | 324 |
357 void PluginInstallerImpl::DownloadPlugin() { | 325 void PluginInstallerImpl::DownloadPlugin() { |
358 set_plugin_installer_state(PluginDownloadInitiated); | 326 set_plugin_installer_state(PluginDownloadInitiated); |
359 | 327 |
360 DLOG(INFO) << "Initiating download for plugin URL " | 328 DLOG(INFO) << "Initiating download for plugin URL " |
361 << plugin_download_url_.c_str(); | 329 << plugin_download_url_.c_str(); |
362 | 330 |
363 DisplayStatus(IDS_DEFAULT_PLUGIN_DOWNLOADING_PLUGIN_MSG); | 331 DisplayStatus(IDS_DEFAULT_PLUGIN_DOWNLOADING_PLUGIN_MSG); |
364 | 332 |
365 if (is_activex_) { | 333 if (!plugin_download_url_for_display_) { |
366 if (activex_installer_ == NULL) { | 334 webkit_glue::DownloadUrl(plugin_download_url_, hwnd()); |
367 CComObject<ActiveXInstaller>::CreateInstance(&activex_installer_); | |
368 activex_installer_->AddRef(); | |
369 } | |
370 activex_installer_->StartDownload(activex_clsid_, activex_codebase_, | |
371 hwnd(), kActivexInstallResult); | |
372 } else { | 335 } else { |
373 if (!plugin_download_url_for_display_) { | 336 default_plugin::g_browser->geturl(instance(), |
374 webkit_glue::DownloadUrl(plugin_download_url_, hwnd()); | 337 plugin_download_url_.c_str(), |
375 } else { | 338 "_blank"); |
376 default_plugin::g_browser->geturl(instance(), | 339 set_plugin_installer_state(PluginInstallerLaunchSuccess); |
377 plugin_download_url_.c_str(), | 340 DisplayStatus(IDS_DEFAULT_PLUGIN_REFRESH_PLUGIN_MSG); |
378 "_blank"); | 341 enable_click_ = true; |
379 set_plugin_installer_state(PluginInstallerLaunchSuccess); | 342 RefreshDisplay(); |
380 DisplayStatus(IDS_DEFAULT_PLUGIN_REFRESH_PLUGIN_MSG); | |
381 enable_click_ = true; | |
382 RefreshDisplay(); | |
383 } | |
384 } | 343 } |
385 } | 344 } |
386 | 345 |
387 void PluginInstallerImpl::DownloadCancelled() { | 346 void PluginInstallerImpl::DownloadCancelled() { |
388 DisplayAvailablePluginStatus(); | 347 DisplayAvailablePluginStatus(); |
389 } | 348 } |
390 | 349 |
391 LRESULT PluginInstallerImpl::OnEraseBackGround(UINT message, WPARAM wparam, | 350 LRESULT PluginInstallerImpl::OnEraseBackGround(UINT message, WPARAM wparam, |
392 LPARAM lparam, BOOL& handled) { | 351 LPARAM lparam, BOOL& handled) { |
393 HDC paint_device_context = reinterpret_cast<HDC>(wparam); | 352 HDC paint_device_context = reinterpret_cast<HDC>(wparam); |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
646 installation_job_monitor_thread_->AssignProcessToJob( | 605 installation_job_monitor_thread_->AssignProcessToJob( |
647 shell_execute_info.hProcess); | 606 shell_execute_info.hProcess); |
648 DisplayStatus(IDS_DEFAULT_PLUGIN_REFRESH_PLUGIN_MSG); | 607 DisplayStatus(IDS_DEFAULT_PLUGIN_REFRESH_PLUGIN_MSG); |
649 enable_click_ = true; | 608 enable_click_ = true; |
650 RefreshDisplay(); | 609 RefreshDisplay(); |
651 } | 610 } |
652 } | 611 } |
653 return 0; | 612 return 0; |
654 } | 613 } |
655 | 614 |
656 LRESULT PluginInstallerImpl::OnActiveXInstallResult(UINT message, | |
657 WPARAM wparam, | |
658 LPARAM lparam, | |
659 BOOL& handled) { | |
660 handled = TRUE; | |
661 | |
662 if (SUCCEEDED(wparam)) { | |
663 set_plugin_installer_state(PluginInstallerLaunchSuccess); | |
664 DisplayStatus(IDS_DEFAULT_PLUGIN_REFRESH_PLUGIN_MSG); | |
665 PostMessage(hwnd(), kRefreshPluginsMessage, 0, 0); | |
666 } else if ((wparam == INET_E_UNKNOWN_PROTOCOL) || | |
667 (wparam == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND))) { | |
668 set_plugin_installer_state(PluginDownloadFailed); | |
669 DisplayPluginDownloadFailedStatus(); | |
670 } else { | |
671 set_plugin_installer_state(PluginInstallerLaunchFailure); | |
672 DisplayStatus(IDS_DEFAULT_PLUGIN_INSTALLATION_FAILED_MSG); | |
673 } | |
674 return 0; | |
675 } | |
676 | |
677 std::string PluginInstallerImpl::ResolveURL(NPP instance, | |
678 const std::string& relative_url) { | |
679 // The NPAPI functions may not be available if this function is called | |
680 // as a result of a unit test. | |
681 if (default_plugin::g_browser) { | |
682 NPObject* object = NULL; | |
683 default_plugin::g_browser->getvalue(instance, NPNVWindowNPObject, &object); | |
684 activex_shim::NPNScriptableObject window(instance, object); | |
685 std::wstring url = | |
686 window.GetObjectProperty("document").GetStringProperty("URL"); | |
687 GURL base(url); | |
688 return base.Resolve(relative_url).spec(); | |
689 } | |
690 return relative_url; | |
691 } | |
692 | |
693 bool PluginInstallerImpl::InitializeResources(HINSTANCE module_handle) { | 615 bool PluginInstallerImpl::InitializeResources(HINSTANCE module_handle) { |
694 DCHECK(icon_ == NULL); | 616 DCHECK(icon_ == NULL); |
695 DCHECK(regular_font_ == NULL); | 617 DCHECK(regular_font_ == NULL); |
696 DCHECK(bold_font_ == NULL); | 618 DCHECK(bold_font_ == NULL); |
697 DCHECK(underline_font_ == NULL); | 619 DCHECK(underline_font_ == NULL); |
698 | 620 |
699 icon_ = LoadIcon(module_handle, MAKEINTRESOURCE(IDI_DEFAULT_PLUGIN_ICON)); | 621 icon_ = LoadIcon(module_handle, MAKEINTRESOURCE(IDI_DEFAULT_PLUGIN_ICON)); |
700 DCHECK(icon_ != NULL); | 622 DCHECK(icon_ != NULL); |
701 | 623 |
702 desired_language_ = "en-us"; | 624 desired_language_ = "en-us"; |
703 regular_font_ = reinterpret_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT)); | 625 regular_font_ = reinterpret_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT)); |
704 DCHECK(regular_font_ != NULL); | 626 DCHECK(regular_font_ != NULL); |
705 | 627 |
706 LOGFONT font_info = {0}; | 628 LOGFONT font_info = {0}; |
707 GetObject(regular_font_, sizeof(LOGFONT), &font_info); | 629 GetObject(regular_font_, sizeof(LOGFONT), &font_info); |
708 font_info.lfWeight |= FW_BOLD; | 630 font_info.lfWeight |= FW_BOLD; |
709 bold_font_ = CreateFontIndirect(&font_info); | 631 bold_font_ = CreateFontIndirect(&font_info); |
710 DCHECK(bold_font_ != NULL); | 632 DCHECK(bold_font_ != NULL); |
711 | 633 |
712 font_info.lfUnderline = TRUE; | 634 font_info.lfUnderline = TRUE; |
713 underline_font_ = CreateFontIndirect(&font_info); | 635 underline_font_ = CreateFontIndirect(&font_info); |
714 DCHECK(underline_font_ != NULL); | 636 DCHECK(underline_font_ != NULL); |
715 return true; | 637 return true; |
716 } | 638 } |
717 | 639 |
718 bool PluginInstallerImpl::ParseInstantiationArguments( | |
719 NPMIMEType mime_type, | |
720 NPP instance, | |
721 int16 argc, | |
722 char* argn[], | |
723 char* argv[], | |
724 std::string* raw_activex_clsid, | |
725 bool* is_activex, | |
726 std::string* activex_clsid, | |
727 std::string* activex_codebase, | |
728 std::string* plugin_download_url, | |
729 std::string* plugin_finder_url) { | |
730 | |
731 if (!raw_activex_clsid || !is_activex || !activex_clsid || | |
732 !plugin_download_url || !plugin_finder_url || !activex_codebase) { | |
733 NOTREACHED(); | |
734 return false; | |
735 } | |
736 | |
737 *is_activex = false; | |
738 | |
739 bool valid_mime_type = (mime_type != NULL ? strlen(mime_type) > 0 : false); | |
740 | |
741 for (int i = 0; i < argc; ++i) { | |
742 // We should only look for activex installation if the mime type passed in | |
743 // is not valid. In any case this code will be taken out when we remove | |
744 // the activex shim. | |
745 if (!valid_mime_type && LowerCaseEqualsASCII(argn[i], "classid") && | |
746 activex_shim::GetClsidFromClassidAttribute(argv[i], | |
747 raw_activex_clsid)) { | |
748 *is_activex = true; | |
749 *activex_clsid = std::string("{") + *raw_activex_clsid + "}"; | |
750 } | |
751 if (LowerCaseEqualsASCII(argn[i], "codebase")) { | |
752 *activex_codebase = ResolveURL(instance, argv[i]); | |
753 size_t pos = activex_codebase->find('#'); | |
754 if (pos != std::string::npos) | |
755 *plugin_download_url = activex_codebase->substr(0, pos); | |
756 else | |
757 *plugin_download_url = *activex_codebase; | |
758 } | |
759 } | |
760 | |
761 if (!*is_activex) { | |
762 if (!valid_mime_type || !instance) { | |
763 DLOG(WARNING) << __FUNCTION__ << " Invalid parameters passed in"; | |
764 NOTREACHED(); | |
765 return false; | |
766 } | |
767 | |
768 if (!webkit_glue::GetPluginFinderURL(plugin_finder_url)) { | |
769 NOTREACHED(); | |
770 DLOG(WARNING) << __FUNCTION__ << " Failed to get the plugin finder URL"; | |
771 return false; | |
772 } | |
773 | |
774 DLOG(INFO) << "Plugin finder URL is " << plugin_finder_url->c_str(); | |
775 } | |
776 | |
777 return true; | |
778 } | |
779 | |
780 void PluginInstallerImpl::NotifyPluginStatus(int status) { | 640 void PluginInstallerImpl::NotifyPluginStatus(int status) { |
781 default_plugin::g_browser->getvalue( | 641 default_plugin::g_browser->getvalue( |
782 instance_, | 642 instance_, |
783 static_cast<NPNVariable>( | 643 static_cast<NPNVariable>( |
784 default_plugin::kMissingPluginStatusStart + status), | 644 default_plugin::kMissingPluginStatusStart + status), |
785 NULL); | 645 NULL); |
786 } | 646 } |
OLD | NEW |