| 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 |