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

Side by Side Diff: plugin/win/main_win.cc

Issue 4957002: - Check for a NULL PluginObject at all NPAPI entry points. This fixes a crash in Chrome where ... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/o3d/
Patch Set: '' Created 10 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « plugin/mac/main_mac.mm ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2009, Google Inc. 2 * Copyright 2009, Google Inc.
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are 6 * modification, are permitted provided that the following conditions are
7 * met: 7 * met:
8 * 8 *
9 * * Redistributions of source code must retain the above copyright 9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 21 matching lines...) Expand all
32 32
33 // This file implements the platform specific parts of the plugin for 33 // This file implements the platform specific parts of the plugin for
34 // the Windows platform. 34 // the Windows platform.
35 35
36 #include "plugin/cross/main.h" 36 #include "plugin/cross/main.h"
37 37
38 #include <windows.h> 38 #include <windows.h>
39 #include <windowsx.h> 39 #include <windowsx.h>
40 #include <shellapi.h> 40 #include <shellapi.h>
41 41
42 #include "base/at_exit.h"
43 #include "base/command_line.h"
44 #include "base/file_util.h"
45 #include "base/logging.h" 42 #include "base/logging.h"
46 #include "base/ref_counted.h"
47 #include "core/cross/display_mode.h" 43 #include "core/cross/display_mode.h"
48 #include "core/cross/event.h" 44 #include "core/cross/event.h"
49 #include "plugin/cross/plugin_logging.h" 45 #include "core/win/display_window_win.h"
50 #include "plugin/cross/out_of_memory.h"
51 #include "plugin/cross/whitelist.h"
52 #include "statsreport/metrics.h"
53 #include "v8/include/v8.h" 46 #include "v8/include/v8.h"
54 #include "breakpad/win/bluescreen_detector.h" 47 #if !defined(O3D_INTERNAL_PLUGIN)
48 #include "breakpad/win/exception_handler_win32.h"
49 #endif
55 50
56 using glue::_o3d::PluginObject; 51 using glue::_o3d::PluginObject;
57 using glue::StreamManager; 52 using glue::StreamManager;
58 using o3d::DisplayWindowWindows; 53 using o3d::DisplayWindowWindows;
59 using o3d::Event; 54 using o3d::Event;
60 55
61 namespace { 56 namespace {
62 // The instance handle of the O3D DLL. 57 // The instance handle of the O3D DLL.
63 HINSTANCE g_module_instance; 58 HINSTANCE g_module_instance;
64 } // namespace anonymous 59 } // namespace anonymous
65 60
66 #if !defined(O3D_INTERNAL_PLUGIN) 61 #if !defined(O3D_INTERNAL_PLUGIN)
67 62 // Used for breakpad crash handling
68 o3d::PluginLogging* g_logger = NULL; 63 static ExceptionManager *g_exception_manager = NULL;
69 bool g_logging_initialized = false;
70 o3d::BluescreenDetector *g_bluescreen_detector = NULL;
71 64
72 extern "C" BOOL WINAPI DllMain(HINSTANCE instance, 65 extern "C" BOOL WINAPI DllMain(HINSTANCE instance,
73 DWORD reason, 66 DWORD reason,
74 LPVOID reserved) { 67 LPVOID reserved) {
75 g_module_instance = instance; 68 g_module_instance = instance;
76 69
77 if (reason == DLL_PROCESS_DETACH) { 70 if (reason == DLL_PROCESS_DETACH) {
78 // Teardown V8 when the plugin dll is unloaded. 71 // Teardown V8 when the plugin dll is unloaded.
79 // NOTE: NP_Shutdown would have been a good place for this code but 72 // NOTE: NP_Shutdown would have been a good place for this code but
80 // unfortunately it looks like it gets called even when the dll 73 // unfortunately it looks like it gets called even when the dll
81 // isn't really unloaded. This is a problem since after calling 74 // isn't really unloaded. This is a problem since after calling
82 // V8::Dispose(), V8 cannot be initialized again. 75 // V8::Dispose(), V8 cannot be initialized again.
83 bool v8_disposed = v8::V8::Dispose(); 76 bool v8_disposed = v8::V8::Dispose();
84 if (!v8_disposed) 77 if (!v8_disposed)
85 DLOG(ERROR) << "Failed to release V8 resources."; 78 DLOG(ERROR) << "Failed to release V8 resources.";
86 return true; 79 return true;
87 } 80 }
88 return true; 81 return true;
89 } 82 }
90 #endif // O3D_INTERNAL_PLUGIN 83 #endif // O3D_INTERNAL_PLUGIN
91 84
92 namespace { 85 namespace {
93 const wchar_t* const kO3DWindowClassName = L"O3DWindowClass"; 86 const wchar_t* const kO3DWindowClassName = L"O3DWindowClass";
94 87
95 void CleanupAllWindows(PluginObject *obj); 88 void CleanupAllWindows(PluginObject *obj);
96 89
97 // We would normally make this a stack variable in main(), but in a
98 // plugin, that's not possible, so we make it a global. When the DLL is loaded
99 // this it gets constructed and when it is unlooaded it is destructed. Note
100 // that this cannot be done in NP_Initialize and NP_Shutdown because those
101 // calls do not necessarily signify the DLL being loaded and unloaded. If the
102 // DLL is not unloaded then the values of global variables are preserved.
103 base::AtExitManager g_at_exit_manager;
104
105 static int HandleKeyboardEvent(PluginObject *obj, 90 static int HandleKeyboardEvent(PluginObject *obj,
106 HWND hWnd, 91 HWND hWnd,
107 UINT Msg, 92 UINT Msg,
108 WPARAM wParam, 93 WPARAM wParam,
109 LPARAM lParam) { 94 LPARAM lParam) {
110 DCHECK(obj); 95 DCHECK(obj);
111 DCHECK(obj->client()); 96 DCHECK(obj->client());
112 Event::Type type; 97 Event::Type type;
113 // First figure out which kind of event to create, and do any event-specific 98 // First figure out which kind of event to create, and do any event-specific
114 // processing that can be done prior to creating it. 99 // processing that can be done prior to creating it.
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 // Tell windows we don't need the background cleared. 459 // Tell windows we don't need the background cleared.
475 return 1; 460 return 1;
476 } 461 }
477 462
478 case WM_TIMER: { 463 case WM_TIMER: {
479 if (reentrance_count.get() > 1) { 464 if (reentrance_count.get() > 1) {
480 break; // Ignore this message; we're reentrant. 465 break; // Ignore this message; we're reentrant.
481 } 466 }
482 467
483 #if !defined(O3D_INTERNAL_PLUGIN) 468 #if !defined(O3D_INTERNAL_PLUGIN)
484 // TODO: Only logging for windows until we figure out the proper
485 // mac way
486 if (g_logger) g_logger->UpdateLogging(); 469 if (g_logger) g_logger->UpdateLogging();
487 #endif 470 #endif
488 471
489 // If rendering continuously, invalidate the window and force a paint if 472 // If rendering continuously, invalidate the window and force a paint if
490 // it is visible. The paint invalidates the renderer and Tick will later 473 // it is visible. The paint invalidates the renderer and Tick will later
491 // repaint the window. 474 // repaint the window.
492 if (obj->client()->NeedsContinuousRender()) { 475 if (obj->client()->NeedsContinuousRender()) {
493 InvalidateRect(obj->GetHWnd(), NULL, FALSE); 476 InvalidateRect(obj->GetHWnd(), NULL, FALSE);
494 UpdateWindow(obj->GetHWnd()); 477 UpdateWindow(obj->GetHWnd());
495 } 478 }
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 window_class.lpszClassName = kO3DWindowClassName; 629 window_class.lpszClassName = kO3DWindowClassName;
647 // We use CS_OWNDC in case we are rendering OpenGL into this window. 630 // We use CS_OWNDC in case we are rendering OpenGL into this window.
648 window_class.style = CS_DBLCLKS | CS_OWNDC; 631 window_class.style = CS_DBLCLKS | CS_OWNDC;
649 return RegisterClassEx(&window_class) != 0; 632 return RegisterClassEx(&window_class) != 0;
650 } 633 }
651 634
652 void UnregisterO3DWindowClass() { 635 void UnregisterO3DWindowClass() {
653 UnregisterClass(kO3DWindowClassName, g_module_instance); 636 UnregisterClass(kO3DWindowClassName, g_module_instance);
654 } 637 }
655 638
656 NPError InitializePlugin() {
657 #if !defined(O3D_INTERNAL_PLUGIN)
658 if (!o3d::SetupOutOfMemoryHandler())
659 return NPERR_MODULE_LOAD_FAILED_ERROR;
660
661 // Setup crash handler
662 if (!g_exception_manager) {
663 g_exception_manager = new ExceptionManager(false);
664 g_exception_manager->StartMonitoring();
665 }
666
667 // Turn on the logging.
668 CommandLine::Init(0, NULL);
669
670 FilePath log;
671 file_util::GetTempDir(&log);
672 log.Append(L"debug.log");
673
674 InitLogging(log.value().c_str(),
675 logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG,
676 logging::DONT_LOCK_LOG_FILE,
677 logging::APPEND_TO_OLD_LOG_FILE);
678 #endif // O3D_INTERNAL_PLUGIN
679
680 DLOG(INFO) << "NP_Initialize";
681
682 if (!RegisterO3DWindowClass())
683 return NPERR_MODULE_LOAD_FAILED_ERROR;
684
685 return NPERR_NO_ERROR;
686 }
687
688 void CleanupAllWindows(PluginObject *obj) { 639 void CleanupAllWindows(PluginObject *obj) {
689 if (obj->GetContentHWnd()) { 640 if (obj->GetContentHWnd()) {
690 ::KillTimer(obj->GetContentHWnd(), 0); 641 ::KillTimer(obj->GetContentHWnd(), 0);
691 PluginObject::ClearPluginProperty(obj->GetContentHWnd()); 642 PluginObject::ClearPluginProperty(obj->GetContentHWnd());
692 ::PostMessage(obj->GetContentHWnd(), kDestroyWindowMessageID, 0, 0); 643 ::PostMessage(obj->GetContentHWnd(), kDestroyWindowMessageID, 0, 0);
693 obj->SetContentHWnd(NULL); 644 obj->SetContentHWnd(NULL);
694 } 645 }
695 646
696 if (obj->GetPluginHWnd()) { 647 if (obj->GetPluginHWnd()) {
697 // Restore the original WNDPROC on the plugin window so that we 648 // Restore the original WNDPROC on the plugin window so that we
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 if (GetMonitorInfo(monitor, &monitor_info)) { 696 if (GetMonitorInfo(monitor, &monitor_info)) {
746 *rect = monitor_info.rcMonitor; 697 *rect = monitor_info.rcMonitor;
747 return true; 698 return true;
748 } else { 699 } else {
749 return false; 700 return false;
750 } 701 }
751 } 702 }
752 703
753 } // namespace anonymous 704 } // namespace anonymous
754 705
755 #if defined(O3D_INTERNAL_PLUGIN)
756 namespace o3d { 706 namespace o3d {
757 #else
758 extern "C" {
759 #endif
760 707
761 NPError OSCALL NP_Initialize(NPNetscapeFuncs *browserFuncs) { 708 NPError PlatformPreNPInitialize() {
762 HANDLE_CRASHES; 709 #if !defined(O3D_INTERNAL_PLUGIN)
763 710 // Setup crash handler
764 NPError retval = InitializeNPNApi(browserFuncs); 711 if (!g_exception_manager) {
765 if (retval != NPERR_NO_ERROR) return retval; 712 g_exception_manager = new ExceptionManager(false);
766 return InitializePlugin(); 713 g_exception_manager->StartMonitoring();
714 }
715 #endif // O3D_INTERNAL_PLUGIN
716 return NPERR_NO_ERROR;
767 } 717 }
768 718
769 NPError OSCALL NP_Shutdown(void) { 719 NPError PlatformPostNPInitialize() {
770 HANDLE_CRASHES; 720 if (!RegisterO3DWindowClass())
771 DLOG(INFO) << "NP_Shutdown"; 721 return NPERR_MODULE_LOAD_FAILED_ERROR;
772 722
723 return NPERR_NO_ERROR;
724 }
725
726 NPError PlatformPreNPShutdown() {
727 // TODO(tschmelcher): Is there a reason we need to do this before the main
728 // shutdown tasks? If not, we can axe the PlatformPreNPShutdown() function.
773 UnregisterO3DWindowClass(); 729 UnregisterO3DWindowClass();
730 return NPERR_NO_ERROR;
731 }
774 732
733 NPError PlatformPostNPShutdown() {
775 #if !defined(O3D_INTERNAL_PLUGIN) 734 #if !defined(O3D_INTERNAL_PLUGIN)
776
777 if (g_logger) {
778 // Do a last sweep to aggregate metrics before we shut down
779 g_logger->ProcessMetrics(true, false, false);
780 delete g_logger;
781 g_logger = NULL;
782 g_logging_initialized = false;
783 stats_report::g_global_metrics.Uninitialize();
784 }
785
786 CommandLine::Reset();
787
788 // TODO : This is commented out until we can determine if 735 // TODO : This is commented out until we can determine if
789 // it's safe to shutdown breakpad at this stage (Gears, for 736 // it's safe to shutdown breakpad at this stage (Gears, for
790 // example, never deletes...) 737 // example, never deletes...)
791 // Shutdown breakpad 738 // Shutdown breakpad
792 // delete g_exception_manager; 739 // delete g_exception_manager;
793
794 // Strictly speaking, on windows, it's not really necessary to call
795 // Stop(), but we do so for completeness
796 if (g_bluescreen_detector) {
797 g_bluescreen_detector->Stop();
798 delete g_bluescreen_detector;
799 g_bluescreen_detector = NULL;
800 }
801
802 #endif // O3D_INTERNAL_PLUGIN
803
804 return NPERR_NO_ERROR;
805 }
806 } // extern "C" / namespace o3d
807
808 namespace o3d {
809
810 NPError NPP_New(NPMIMEType pluginType,
811 NPP instance,
812 uint16 mode,
813 int16 argc,
814 char *argn[],
815 char *argv[],
816 NPSavedData *saved) {
817 HANDLE_CRASHES;
818
819 #if !defined(O3D_INTERNAL_PLUGIN)
820 if (!g_logging_initialized) {
821 // Get user config metrics. These won't be stored though unless the user
822 // opts-in for usagestats logging
823 GetUserAgentMetrics(instance);
824 GetUserConfigMetrics();
825 // Create usage stats logs object
826 g_logger = o3d::PluginLogging::InitializeUsageStatsLogging();
827 if (g_logger) {
828 // Setup blue-screen detection
829 g_bluescreen_detector = new o3d::BluescreenDetector();
830 g_bluescreen_detector->Start();
831 }
832 g_logging_initialized = true;
833 }
834 #endif 740 #endif
835 741
836 if (!IsDomainAuthorized(instance)) {
837 return NPERR_INVALID_URL;
838 }
839
840 PluginObject* pluginObject = glue::_o3d::PluginObject::Create(
841 instance);
842 instance->pdata = pluginObject;
843 glue::_o3d::InitializeGlue(instance);
844 pluginObject->Init(argc, argn, argv);
845 return NPERR_NO_ERROR;
846 }
847
848 NPError NPP_Destroy(NPP instance, NPSavedData **save) {
849 HANDLE_CRASHES;
850 PluginObject *obj = static_cast<PluginObject*>(instance->pdata);
851 if (obj) {
852 if (obj->GetHWnd()) {
853 CleanupAllWindows(obj);
854 }
855
856 obj->TearDown();
857 NPN_ReleaseObject(obj);
858 instance->pdata = NULL;
859 }
860
861 return NPERR_NO_ERROR; 742 return NPERR_NO_ERROR;
862 } 743 }
863 744
864 NPError PlatformNPPGetValue(NPP instance, NPPVariable variable, void *value) { 745 NPError PlatformNPPNew(NPP instance, PluginObject *obj) {
746 return NPERR_NO_ERROR;
747 }
748
749 NPError PlatformNPPDestroy(NPP instance, PluginObject *obj) {
750 if (obj->GetHWnd()) {
751 CleanupAllWindows(obj);
752 }
753
754 obj->TearDown();
755 return NPERR_NO_ERROR;
756 }
757
758 NPError PlatformNPPGetValue(PluginObject *obj,
759 NPPVariable variable,
760 void *value) {
865 return NPERR_INVALID_PARAM; 761 return NPERR_INVALID_PARAM;
866 } 762 }
867 763
868 NPError NPP_SetWindow(NPP instance, NPWindow *window) { 764 NPError PlatformNPPSetWindow(NPP instance,
869 HANDLE_CRASHES; 765 PluginObject *obj,
870 PluginObject *obj = static_cast<PluginObject*>(instance->pdata); 766 NPWindow *window) {
871
872 HWND hWnd = static_cast<HWND>(window->window); 767 HWND hWnd = static_cast<HWND>(window->window);
873 if (!hWnd) { 768 if (!hWnd) {
874 // Chrome calls us this way before NPP_Destroy. 769 // Chrome calls us this way before NPP_Destroy.
875 if (obj->GetHWnd()) { 770 if (obj->GetHWnd()) {
876 CleanupAllWindows(obj); 771 CleanupAllWindows(obj);
877 } 772 }
878 return NPERR_NO_ERROR; 773 return NPERR_NO_ERROR;
879 } 774 }
880 775
881 if (obj->GetPluginHWnd() == hWnd) { 776 if (obj->GetPluginHWnd() == hWnd) {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
941 obj->client()->Init(); 836 obj->client()->Init();
942 837
943 // we set the timer to 10ms or 100fps. At the time of this comment 838 // we set the timer to 10ms or 100fps. At the time of this comment
944 // the renderer does a vsync the max fps it will run will be the refresh 839 // the renderer does a vsync the max fps it will run will be the refresh
945 // rate of the monitor or 100fps, which ever is lower. 840 // rate of the monitor or 100fps, which ever is lower.
946 ::SetTimer(obj->GetHWnd(), 0, 10, NULL); 841 ::SetTimer(obj->GetHWnd(), 0, 10, NULL);
947 842
948 return NPERR_NO_ERROR; 843 return NPERR_NO_ERROR;
949 } 844 }
950 845
951 // Called when the browser has finished attempting to stream data to 846 void PlatformNPPStreamAsFile(StreamManager *stream_manager,
952 // a file as requested. If fname == NULL the attempt was not successful. 847 NPStream *stream,
953 void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname) { 848 const char *fname) {
954 HANDLE_CRASHES;
955 PluginObject *obj = static_cast<PluginObject*>(instance->pdata);
956 StreamManager *stream_manager = obj->stream_manager();
957
958 stream_manager->SetStreamFile(stream, fname); 849 stream_manager->SetStreamFile(stream, fname);
959 } 850 }
960 851
961 int16 NPP_HandleEvent(NPP instance, void *event) { 852 int16 PlatformNPPHandleEvent(NPP instance, PluginObject *obj, void *event) {
962 HANDLE_CRASHES;
963 return 0; 853 return 0;
964 } 854 }
855
965 } // namespace o3d 856 } // namespace o3d
966 857
858 // TODO(tschmelcher): This stuff does not belong in this file.
967 namespace glue { 859 namespace glue {
968 namespace _o3d { 860 namespace _o3d {
969 bool PluginObject::GetDisplayMode(int mode_id, o3d::DisplayMode *mode) { 861 bool PluginObject::GetDisplayMode(int mode_id, o3d::DisplayMode *mode) {
970 return renderer()->GetDisplayMode(mode_id, mode); 862 return renderer()->GetDisplayMode(mode_id, mode);
971 } 863 }
972 864
973 // TODO: Where should this really live? It's platform-specific, but in 865 // TODO: Where should this really live? It's platform-specific, but in
974 // PluginObject, which mainly lives in cross/o3d_glue.h+cc. 866 // PluginObject, which mainly lives in cross/o3d_glue.h+cc.
975 bool PluginObject::RequestFullscreenDisplay() { 867 bool PluginObject::RequestFullscreenDisplay() {
976 bool success = false; 868 bool success = false;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1035 if (!renderer_->CancelFullscreen(display, prev_width_, prev_height_)) { 927 if (!renderer_->CancelFullscreen(display, prev_width_, prev_height_)) {
1036 LOG(FATAL) << "Failed to get the renderer out of fullscreen mode!"; 928 LOG(FATAL) << "Failed to get the renderer out of fullscreen mode!";
1037 } 929 }
1038 ReplaceContentWindow(GetContentHWnd(), GetPluginHWnd(), 930 ReplaceContentWindow(GetContentHWnd(), GetPluginHWnd(),
1039 prev_width_, prev_height_); 931 prev_width_, prev_height_);
1040 client()->SendResizeEvent(prev_width_, prev_height_, false); 932 client()->SendResizeEvent(prev_width_, prev_height_, false);
1041 } 933 }
1042 } 934 }
1043 } // namespace _o3d 935 } // namespace _o3d
1044 } // namespace glue 936 } // namespace glue
OLDNEW
« no previous file with comments | « plugin/mac/main_mac.mm ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698