Remove Legacy NPAPI Flash Sandbox support
BUG=153599 Review URL: https://chromiumcodereview.appspot.com/11049004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@160310 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
chrome/common
content
browser
common
plugin
public
webkit/plugins/npapi
@@ -310,60 +310,6 @@ bool GetBundledPepperFlash(content::PepperPluginInfo* plugin,
|
|||||||
#endif // FLAPPER_AVAILABLE
|
#endif // FLAPPER_AVAILABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
// Launches the privileged flash broker, used when flash is sandboxed.
|
|
||||||
// The broker is the same flash dll, except that it uses a different
|
|
||||||
// entrypoint (BrokerMain) and it is hosted in windows' generic surrogate
|
|
||||||
// process rundll32. After launching the broker we need to pass to
|
|
||||||
// the flash plugin the process id of the broker via the command line
|
|
||||||
// using --flash-broker=pid.
|
|
||||||
// More info about rundll32 at http://support.microsoft.com/kb/164787.
|
|
||||||
bool LoadFlashBroker(const FilePath& plugin_path, CommandLine* cmd_line) {
|
|
||||||
FilePath rundll;
|
|
||||||
if (!PathService::Get(base::DIR_SYSTEM, &rundll))
|
|
||||||
return false;
|
|
||||||
rundll = rundll.AppendASCII("rundll32.exe");
|
|
||||||
// Rundll32 cannot handle paths with spaces, so we use the short path.
|
|
||||||
wchar_t short_path[MAX_PATH];
|
|
||||||
if (0 == ::GetShortPathNameW(plugin_path.value().c_str(),
|
|
||||||
short_path, arraysize(short_path)))
|
|
||||||
return false;
|
|
||||||
// Here is the kicker, if the user has disabled 8.3 (short path) support
|
|
||||||
// on the volume GetShortPathNameW does not fail but simply returns the
|
|
||||||
// input path. In this case if the path had any spaces then rundll32 will
|
|
||||||
// incorrectly interpret its parameters. So we quote the path, even though
|
|
||||||
// the kb/164787 says you should not.
|
|
||||||
std::wstring cmd_final =
|
|
||||||
base::StringPrintf(L"%ls \"%ls\",BrokerMain browser=chrome",
|
|
||||||
rundll.value().c_str(),
|
|
||||||
short_path);
|
|
||||||
base::ProcessHandle process;
|
|
||||||
base::LaunchOptions options;
|
|
||||||
options.start_hidden = true;
|
|
||||||
if (!base::LaunchProcess(cmd_final, options, &process))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
cmd_line->AppendSwitchASCII("flash-broker",
|
|
||||||
base::Int64ToString(::GetProcessId(process)));
|
|
||||||
|
|
||||||
// The flash broker, unders some circumstances can linger beyond the lifetime
|
|
||||||
// of the flash player, so we put it in a job object, when the browser
|
|
||||||
// terminates the job object is destroyed (by the OS) and the flash broker
|
|
||||||
// is terminated.
|
|
||||||
HANDLE job = ::CreateJobObjectW(NULL, NULL);
|
|
||||||
if (base::SetJobObjectAsKillOnJobClose(job)) {
|
|
||||||
::AssignProcessToJobObject(job, process);
|
|
||||||
// Yes, we are leaking the object here. Read comment above.
|
|
||||||
} else {
|
|
||||||
::CloseHandle(job);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
::CloseHandle(process);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif // OS_WIN
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace chrome {
|
namespace chrome {
|
||||||
@@ -464,70 +410,6 @@ gfx::Image& ChromeContentClient::GetNativeImageNamed(int resource_id) const {
|
|||||||
return ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id);
|
return ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
bool ChromeContentClient::SandboxPlugin(CommandLine* command_line,
|
|
||||||
sandbox::TargetPolicy* policy) {
|
|
||||||
std::wstring plugin_dll = command_line->
|
|
||||||
GetSwitchValueNative(switches::kPluginPath);
|
|
||||||
|
|
||||||
FilePath builtin_flash;
|
|
||||||
if (!PathService::Get(chrome::FILE_FLASH_PLUGIN_EXISTING, &builtin_flash))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
FilePath plugin_path(plugin_dll);
|
|
||||||
if (plugin_path.BaseName() != builtin_flash.BaseName())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (base::win::GetVersion() <= base::win::VERSION_XP ||
|
|
||||||
CommandLine::ForCurrentProcess()->HasSwitch(
|
|
||||||
switches::kDisableFlashSandbox)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add policy for the plugin proxy window pump event
|
|
||||||
// used by WebPluginDelegateProxy::HandleInputEvent().
|
|
||||||
if (policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
|
|
||||||
sandbox::TargetPolicy::HANDLES_DUP_ANY,
|
|
||||||
L"Event") != sandbox::SBOX_ALL_OK) {
|
|
||||||
NOTREACHED();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the policy for the pipes.
|
|
||||||
if (policy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES,
|
|
||||||
sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY,
|
|
||||||
L"\\\\.\\pipe\\chrome.*") != sandbox::SBOX_ALL_OK) {
|
|
||||||
NOTREACHED();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spawn the flash broker and apply sandbox policy.
|
|
||||||
if (LoadFlashBroker(plugin_path, command_line)) {
|
|
||||||
// UI job restrictions break windowless Flash, so just pick up single
|
|
||||||
// process limit for now.
|
|
||||||
policy->SetJobLevel(sandbox::JOB_UNPROTECTED, 0);
|
|
||||||
policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
|
|
||||||
sandbox::USER_INTERACTIVE);
|
|
||||||
// Allow the Flash plugin to forward some messages back to Chrome.
|
|
||||||
if (base::win::GetVersion() == base::win::VERSION_VISTA) {
|
|
||||||
// Per-window message filters required on Win7 or later must be added to:
|
|
||||||
// render_widget_host_view_win.cc RenderWidgetHostViewWin::ReparentWindow
|
|
||||||
::ChangeWindowMessageFilter(WM_MOUSEWHEEL, MSGFLT_ADD);
|
|
||||||
::ChangeWindowMessageFilter(WM_APPCOMMAND, MSGFLT_ADD);
|
|
||||||
}
|
|
||||||
policy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
|
|
||||||
} else {
|
|
||||||
// Could not start the broker, use a very weak policy instead.
|
|
||||||
DLOG(WARNING) << "Failed to start flash broker";
|
|
||||||
policy->SetJobLevel(sandbox::JOB_UNPROTECTED, 0);
|
|
||||||
policy->SetTokenLevel(
|
|
||||||
sandbox::USER_UNPROTECTED, sandbox::USER_UNPROTECTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(OS_MACOSX) && !defined(OS_IOS)
|
#if defined(OS_MACOSX) && !defined(OS_IOS)
|
||||||
bool ChromeContentClient::GetSandboxProfileForSandboxType(
|
bool ChromeContentClient::GetSandboxProfileForSandboxType(
|
||||||
int sandbox_type,
|
int sandbox_type,
|
||||||
|
@@ -38,11 +38,6 @@ class ChromeContentClient : public content::ContentClient {
|
|||||||
ui::ScaleFactor scale_factor) const OVERRIDE;
|
ui::ScaleFactor scale_factor) const OVERRIDE;
|
||||||
virtual gfx::Image& GetNativeImageNamed(int resource_id) const OVERRIDE;
|
virtual gfx::Image& GetNativeImageNamed(int resource_id) const OVERRIDE;
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
virtual bool SandboxPlugin(CommandLine* command_line,
|
|
||||||
sandbox::TargetPolicy* policy) OVERRIDE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(OS_MACOSX) && !defined(OS_IOS)
|
#if defined(OS_MACOSX) && !defined(OS_IOS)
|
||||||
virtual bool GetSandboxProfileForSandboxType(
|
virtual bool GetSandboxProfileForSandboxType(
|
||||||
int sandbox_type,
|
int sandbox_type,
|
||||||
|
@@ -58,24 +58,6 @@ using content::ChildProcessHost;
|
|||||||
#include "webkit/plugins/npapi/plugin_constants_win.h"
|
#include "webkit/plugins/npapi/plugin_constants_win.h"
|
||||||
#include "webkit/plugins/npapi/webplugin_delegate_impl.h"
|
#include "webkit/plugins/npapi/webplugin_delegate_impl.h"
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
void ReparentPluginWindowHelper(HWND window, HWND parent) {
|
|
||||||
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
|
||||||
|
|
||||||
int window_style = WS_CHILD;
|
|
||||||
if (!webkit::npapi::WebPluginDelegateImpl::IsDummyActivationWindow(window))
|
|
||||||
window_style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
|
||||||
|
|
||||||
::SetWindowLongPtr(window, GWL_STYLE, window_style);
|
|
||||||
::SetParent(window, parent);
|
|
||||||
// Allow the Flash plugin to forward some messages back to Chrome.
|
|
||||||
if (base::win::GetVersion() >= base::win::VERSION_WIN7)
|
|
||||||
::SetPropW(parent, webkit::npapi::kNativeWindowClassFilterProp, HANDLE(-1));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void PluginProcessHost::OnPluginWindowDestroyed(HWND window, HWND parent) {
|
void PluginProcessHost::OnPluginWindowDestroyed(HWND window, HWND parent) {
|
||||||
// The window is destroyed at this point, we just care about its parent, which
|
// The window is destroyed at this point, we just care about its parent, which
|
||||||
// is the intermediate window we created.
|
// is the intermediate window we created.
|
||||||
@@ -92,25 +74,6 @@ void PluginProcessHost::AddWindow(HWND window) {
|
|||||||
plugin_parent_windows_set_.insert(window);
|
plugin_parent_windows_set_.insert(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PluginProcessHost::OnReparentPluginWindow(HWND window, HWND parent) {
|
|
||||||
// Reparent only from the plugin process to our process.
|
|
||||||
DWORD process_id = 0;
|
|
||||||
::GetWindowThreadProcessId(window, &process_id);
|
|
||||||
if (process_id != ::GetProcessId(process_->GetHandle()))
|
|
||||||
return;
|
|
||||||
::GetWindowThreadProcessId(parent, &process_id);
|
|
||||||
if (process_id != ::GetCurrentProcessId())
|
|
||||||
return;
|
|
||||||
|
|
||||||
BrowserThread::PostTask(
|
|
||||||
BrowserThread::UI, FROM_HERE,
|
|
||||||
base::Bind(ReparentPluginWindowHelper, window, parent));
|
|
||||||
}
|
|
||||||
|
|
||||||
void PluginProcessHost::OnReportExecutableMemory(size_t size) {
|
|
||||||
// TODO(jschuh): move this into the plugin process once it supports UMA.
|
|
||||||
UMA_HISTOGRAM_MEMORY_KB("Plugin.ExecPageSizeKB", size / 1024);
|
|
||||||
}
|
|
||||||
#endif // defined(OS_WIN)
|
#endif // defined(OS_WIN)
|
||||||
|
|
||||||
#if defined(TOOLKIT_GTK)
|
#if defined(TOOLKIT_GTK)
|
||||||
@@ -317,10 +280,6 @@ bool PluginProcessHost::OnMessageReceived(const IPC::Message& msg) {
|
|||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginWindowDestroyed,
|
IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginWindowDestroyed,
|
||||||
OnPluginWindowDestroyed)
|
OnPluginWindowDestroyed)
|
||||||
IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ReparentPluginWindow,
|
|
||||||
OnReparentPluginWindow)
|
|
||||||
IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ReportExecutableMemory,
|
|
||||||
OnReportExecutableMemory)
|
|
||||||
#endif
|
#endif
|
||||||
#if defined(TOOLKIT_GTK)
|
#if defined(TOOLKIT_GTK)
|
||||||
IPC_MESSAGE_HANDLER(PluginProcessHostMsg_MapNativeViewId,
|
IPC_MESSAGE_HANDLER(PluginProcessHostMsg_MapNativeViewId,
|
||||||
|
@@ -131,8 +131,6 @@ class CONTENT_EXPORT PluginProcessHost
|
|||||||
|
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
void OnPluginWindowDestroyed(HWND window, HWND parent);
|
void OnPluginWindowDestroyed(HWND window, HWND parent);
|
||||||
void OnReparentPluginWindow(HWND window, HWND parent);
|
|
||||||
void OnReportExecutableMemory(size_t size);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_X11)
|
#if defined(USE_X11)
|
||||||
|
@@ -147,16 +147,6 @@ HWND ReparentWindow(HWND window) {
|
|||||||
WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
|
WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
|
||||||
0, 0, 0, 0, orig_parent, 0, instance, 0);
|
0, 0, 0, 0, orig_parent, 0, instance, 0);
|
||||||
ui::CheckWindowCreated(parent);
|
ui::CheckWindowCreated(parent);
|
||||||
// If UIPI is enabled we need to add message filters for parents with
|
|
||||||
// children that cross process boundaries.
|
|
||||||
if (::GetPropW(orig_parent, webkit::npapi::kNativeWindowClassFilterProp)) {
|
|
||||||
// Process-wide message filters required on Vista must be added to:
|
|
||||||
// chrome_content_client.cc ChromeContentClient::SandboxPlugin
|
|
||||||
ChangeWindowMessageFilterEx(parent, WM_MOUSEWHEEL, MSGFLT_ALLOW, NULL);
|
|
||||||
ChangeWindowMessageFilterEx(parent, WM_GESTURE, MSGFLT_ALLOW, NULL);
|
|
||||||
ChangeWindowMessageFilterEx(parent, WM_APPCOMMAND, MSGFLT_ALLOW, NULL);
|
|
||||||
::RemovePropW(orig_parent, webkit::npapi::kNativeWindowClassFilterProp);
|
|
||||||
}
|
|
||||||
::SetParent(window, parent);
|
::SetParent(window, parent);
|
||||||
// How many times we try to find a PluginProcessHost whose process matches
|
// How many times we try to find a PluginProcessHost whose process matches
|
||||||
// the HWND.
|
// the HWND.
|
||||||
|
@@ -92,13 +92,6 @@ IPC_MESSAGE_CONTROL1(PluginProcessHostMsg_ChannelCreated,
|
|||||||
IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_PluginWindowDestroyed,
|
IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_PluginWindowDestroyed,
|
||||||
HWND /* window */,
|
HWND /* window */,
|
||||||
HWND /* parent */)
|
HWND /* parent */)
|
||||||
|
|
||||||
IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_ReparentPluginWindow,
|
|
||||||
HWND /* window */,
|
|
||||||
HWND /* parent */)
|
|
||||||
|
|
||||||
IPC_MESSAGE_CONTROL1(PluginProcessHostMsg_ReportExecutableMemory,
|
|
||||||
uint32_t /* size */)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_X11)
|
#if defined(USE_X11)
|
||||||
|
@@ -111,16 +111,6 @@ const wchar_t* const kTroublesomeDlls[] = {
|
|||||||
L"winstylerthemehelper.dll" // Tuneup utilities 2006.
|
L"winstylerthemehelper.dll" // Tuneup utilities 2006.
|
||||||
};
|
};
|
||||||
|
|
||||||
// The DLLs listed here are known (or under strong suspicion) of causing crashes
|
|
||||||
// when they are loaded in the plugin process.
|
|
||||||
const wchar_t* const kTroublesomePluginDlls[] = {
|
|
||||||
L"rpmainbrowserrecordplugin.dll", // RealPlayer.
|
|
||||||
L"rpchromebrowserrecordhelper.dll", // RealPlayer.
|
|
||||||
L"rpchrome10browserrecordhelper.dll", // RealPlayer.
|
|
||||||
L"ycwebcamerasource.ax" // Cyberlink Camera helper.
|
|
||||||
L"CLRGL.ax" // Cyberlink Camera helper.
|
|
||||||
};
|
|
||||||
|
|
||||||
// The DLLs listed here are known (or under strong suspicion) of causing crashes
|
// The DLLs listed here are known (or under strong suspicion) of causing crashes
|
||||||
// when they are loaded in the GPU process.
|
// when they are loaded in the GPU process.
|
||||||
const wchar_t* const kTroublesomeGpuDlls[] = {
|
const wchar_t* const kTroublesomeGpuDlls[] = {
|
||||||
@@ -242,13 +232,6 @@ void AddGenericDllEvictionPolicy(sandbox::TargetPolicy* policy) {
|
|||||||
BlacklistAddOneDll(kTroublesomeDlls[ix], true, policy);
|
BlacklistAddOneDll(kTroublesomeDlls[ix], true, policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same as AddGenericDllEvictionPolicy but specifically for plugins. In this
|
|
||||||
// case we add the blacklisted dlls even if they are not loaded in this process.
|
|
||||||
void AddPluginDllEvictionPolicy(sandbox::TargetPolicy* policy) {
|
|
||||||
for (int ix = 0; ix != arraysize(kTroublesomePluginDlls); ++ix)
|
|
||||||
BlacklistAddOneDll(kTroublesomePluginDlls[ix], false, policy);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Same as AddGenericDllEvictionPolicy but specifically for the GPU process.
|
// Same as AddGenericDllEvictionPolicy but specifically for the GPU process.
|
||||||
// In this we add the blacklisted dlls even if they are not loaded in this
|
// In this we add the blacklisted dlls even if they are not loaded in this
|
||||||
// process.
|
// process.
|
||||||
@@ -754,26 +737,16 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line,
|
|||||||
// to create separate pretetch settings for browser, renderer etc.
|
// to create separate pretetch settings for browser, renderer etc.
|
||||||
cmd_line->AppendArg(base::StringPrintf("/prefetch:%d", type));
|
cmd_line->AppendArg(base::StringPrintf("/prefetch:%d", type));
|
||||||
|
|
||||||
sandbox::ResultCode result;
|
|
||||||
base::win::ScopedProcessInformation target;
|
|
||||||
sandbox::TargetPolicy* policy = g_broker_services->CreatePolicy();
|
|
||||||
|
|
||||||
#if !defined(NACL_WIN64) // We don't need this code on win nacl64.
|
|
||||||
if (type == content::PROCESS_TYPE_PLUGIN &&
|
|
||||||
!browser_command_line.HasSwitch(switches::kNoSandbox) &&
|
|
||||||
content::GetContentClient()->SandboxPlugin(cmd_line, policy)) {
|
|
||||||
in_sandbox = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!in_sandbox) {
|
if (!in_sandbox) {
|
||||||
policy->Release();
|
|
||||||
base::ProcessHandle process = 0;
|
base::ProcessHandle process = 0;
|
||||||
base::LaunchProcess(*cmd_line, base::LaunchOptions(), &process);
|
base::LaunchProcess(*cmd_line, base::LaunchOptions(), &process);
|
||||||
g_broker_services->AddTargetPeer(process);
|
g_broker_services->AddTargetPeer(process);
|
||||||
return process;
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base::win::ScopedProcessInformation target;
|
||||||
|
sandbox::TargetPolicy* policy = g_broker_services->CreatePolicy();
|
||||||
|
|
||||||
// TODO(jschuh): Make NaCl work with DEP and SEHOP. crbug.com/147752
|
// TODO(jschuh): Make NaCl work with DEP and SEHOP. crbug.com/147752
|
||||||
sandbox::MitigationFlags mitigations = MITIGATION_HEAP_TERMINATE |
|
sandbox::MitigationFlags mitigations = MITIGATION_HEAP_TERMINATE |
|
||||||
MITIGATION_BOTTOM_UP_ASLR |
|
MITIGATION_BOTTOM_UP_ASLR |
|
||||||
@@ -804,10 +777,7 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line,
|
|||||||
|
|
||||||
SetJobLevel(*cmd_line, JOB_LOCKDOWN, 0, policy);
|
SetJobLevel(*cmd_line, JOB_LOCKDOWN, 0, policy);
|
||||||
|
|
||||||
if (type == content::PROCESS_TYPE_PLUGIN) {
|
if (type == content::PROCESS_TYPE_GPU) {
|
||||||
AddGenericDllEvictionPolicy(policy);
|
|
||||||
AddPluginDllEvictionPolicy(policy);
|
|
||||||
} else if (type == content::PROCESS_TYPE_GPU) {
|
|
||||||
if (!AddPolicyForGPU(cmd_line, policy))
|
if (!AddPolicyForGPU(cmd_line, policy))
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -836,6 +806,7 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sandbox::ResultCode result;
|
||||||
if (!exposed_dir.empty()) {
|
if (!exposed_dir.empty()) {
|
||||||
result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
|
result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
|
||||||
sandbox::TargetPolicy::FILES_ALLOW_ANY,
|
sandbox::TargetPolicy::FILES_ALLOW_ANY,
|
||||||
|
@@ -41,56 +41,6 @@ void InitializeChromeApplication();
|
|||||||
void WorkaroundFlashLAHF();
|
void WorkaroundFlashLAHF();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
// This function is provided so that the built-in flash can lock down the
|
|
||||||
// sandbox by calling DelayedLowerToken(0).
|
|
||||||
extern "C" DWORD __declspec(dllexport) __stdcall DelayedLowerToken(void* ts) {
|
|
||||||
// s_ts is only set the first time the function is called, which happens
|
|
||||||
// in PluginMain.
|
|
||||||
static sandbox::TargetServices* s_ts =
|
|
||||||
reinterpret_cast<sandbox::TargetServices*>(ts);
|
|
||||||
if (ts)
|
|
||||||
return 0;
|
|
||||||
s_ts->LowerToken();
|
|
||||||
return 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Returns true if the plugin to be loaded is the internal flash.
|
|
||||||
bool IsPluginBuiltInFlash(const CommandLine& cmd_line) {
|
|
||||||
FilePath path = cmd_line.GetSwitchValuePath(switches::kPluginPath);
|
|
||||||
return (path.BaseName() == FilePath(L"gcswf32.dll"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Before we lock down the flash sandbox, we need to activate the IME machinery
|
|
||||||
// and attach it to this process. (Windows attaches an IME machinery to this
|
|
||||||
// process automatically while it creates its first top-level window.) After
|
|
||||||
// lock down it seems it is unable to start. Note that we leak the IME context
|
|
||||||
// on purpose.
|
|
||||||
HWND g_ime_window = NULL;
|
|
||||||
|
|
||||||
int PreloadIMEForFlash() {
|
|
||||||
HIMC imc = ::ImmCreateContext();
|
|
||||||
if (!imc)
|
|
||||||
return 0;
|
|
||||||
if (::ImmGetOpenStatus(imc))
|
|
||||||
return 1;
|
|
||||||
if (!g_ime_window) {
|
|
||||||
g_ime_window = CreateWindowEx(WS_EX_TOOLWINDOW, L"EDIT", L"", WS_POPUP,
|
|
||||||
0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL), NULL);
|
|
||||||
SetWindowLongPtr(g_ime_window, GWL_EXSTYLE, WS_EX_NOACTIVATE);
|
|
||||||
}
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DestroyIMEForFlash() {
|
|
||||||
if (g_ime_window) {
|
|
||||||
DestroyWindow(g_ime_window);
|
|
||||||
g_ime_window = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// main() routine for running as the plugin process.
|
// main() routine for running as the plugin process.
|
||||||
int PluginMain(const content::MainFunctionParams& parameters) {
|
int PluginMain(const content::MainFunctionParams& parameters) {
|
||||||
// The main thread of the plugin services UI.
|
// The main thread of the plugin services UI.
|
||||||
@@ -115,27 +65,9 @@ int PluginMain(const content::MainFunctionParams& parameters) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif defined(OS_WIN)
|
#elif defined(OS_WIN)
|
||||||
sandbox::TargetServices* target_services =
|
|
||||||
parameters.sandbox_info->target_services;
|
|
||||||
|
|
||||||
base::win::ScopedCOMInitializer com_initializer;
|
base::win::ScopedCOMInitializer com_initializer;
|
||||||
|
|
||||||
DVLOG(1) << "Started plugin with "
|
|
||||||
<< parsed_command_line.GetCommandLineString();
|
|
||||||
|
|
||||||
HMODULE sandbox_test_module = NULL;
|
|
||||||
bool no_sandbox = parsed_command_line.HasSwitch(switches::kNoSandbox);
|
|
||||||
|
|
||||||
if (target_services && !no_sandbox) {
|
|
||||||
// The command line might specify a test plugin to load.
|
|
||||||
if (parsed_command_line.HasSwitch(switches::kTestSandbox)) {
|
|
||||||
std::wstring test_plugin_name =
|
|
||||||
parsed_command_line.GetSwitchValueNative(switches::kTestSandbox);
|
|
||||||
sandbox_test_module = LoadLibrary(test_plugin_name.c_str());
|
|
||||||
DCHECK(sandbox_test_module);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (parsed_command_line.HasSwitch(switches::kPluginStartupDialog)) {
|
if (parsed_command_line.HasSwitch(switches::kPluginStartupDialog)) {
|
||||||
ChildProcess::WaitForDebugger("Plugin");
|
ChildProcess::WaitForDebugger("Plugin");
|
||||||
}
|
}
|
||||||
@@ -143,48 +75,8 @@ int PluginMain(const content::MainFunctionParams& parameters) {
|
|||||||
{
|
{
|
||||||
ChildProcess plugin_process;
|
ChildProcess plugin_process;
|
||||||
plugin_process.set_main_thread(new PluginThread());
|
plugin_process.set_main_thread(new PluginThread());
|
||||||
#if defined(OS_WIN)
|
|
||||||
if (!no_sandbox && target_services) {
|
|
||||||
// We are sandboxing the plugin. If it is a generic plug-in, we lock down
|
|
||||||
// the sandbox right away, but if it is the built-in flash we let flash
|
|
||||||
// start elevated and it will call DelayedLowerToken(0) when it's ready.
|
|
||||||
if (IsPluginBuiltInFlash(parsed_command_line)) {
|
|
||||||
DVLOG(1) << "Sandboxing flash";
|
|
||||||
|
|
||||||
if (!PreloadIMEForFlash())
|
|
||||||
DVLOG(1) << "IME preload failed";
|
|
||||||
DelayedLowerToken(target_services);
|
|
||||||
} else {
|
|
||||||
target_services->LowerToken();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sandbox_test_module) {
|
|
||||||
RunPluginTests run_security_tests =
|
|
||||||
reinterpret_cast<RunPluginTests>(GetProcAddress(sandbox_test_module,
|
|
||||||
kPluginTestCall));
|
|
||||||
DCHECK(run_security_tests);
|
|
||||||
if (run_security_tests) {
|
|
||||||
int test_count = 0;
|
|
||||||
DVLOG(1) << "Running plugin security tests";
|
|
||||||
BOOL result = run_security_tests(&test_count);
|
|
||||||
DCHECK(result) << "Test number " << test_count << " has failed.";
|
|
||||||
// If we are in release mode, crash or debug the process.
|
|
||||||
if (!result) {
|
|
||||||
__debugbreak();
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeLibrary(sandbox_test_module);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MessageLoop::current()->Run();
|
MessageLoop::current()->Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
DestroyIMEForFlash();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -148,16 +148,6 @@ void WebPluginProxy::SetWindowlessPumpEvent(HANDLE pump_messages_event) {
|
|||||||
Send(new PluginHostMsg_SetWindowlessPumpEvent(
|
Send(new PluginHostMsg_SetWindowlessPumpEvent(
|
||||||
route_id_, pump_messages_event_for_renderer));
|
route_id_, pump_messages_event_for_renderer));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebPluginProxy::ReparentPluginWindow(HWND window, HWND parent) {
|
|
||||||
PluginThread::current()->Send(
|
|
||||||
new PluginProcessHostMsg_ReparentPluginWindow(window, parent));
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebPluginProxy::ReportExecutableMemory(size_t size) {
|
|
||||||
PluginThread::current()->Send(
|
|
||||||
new PluginProcessHostMsg_ReportExecutableMemory(size));
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void WebPluginProxy::CancelResource(unsigned long id) {
|
void WebPluginProxy::CancelResource(unsigned long id) {
|
||||||
|
@@ -67,8 +67,6 @@ class WebPluginProxy : public webkit::npapi::WebPlugin {
|
|||||||
virtual void WillDestroyWindow(gfx::PluginWindowHandle window) OVERRIDE;
|
virtual void WillDestroyWindow(gfx::PluginWindowHandle window) OVERRIDE;
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
void SetWindowlessPumpEvent(HANDLE pump_messages_event);
|
void SetWindowlessPumpEvent(HANDLE pump_messages_event);
|
||||||
void ReparentPluginWindow(HWND window, HWND parent);
|
|
||||||
void ReportExecutableMemory(size_t size);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
virtual void CancelResource(unsigned long id) OVERRIDE;
|
virtual void CancelResource(unsigned long id) OVERRIDE;
|
||||||
|
@@ -83,13 +83,6 @@ gfx::Image& ContentClient::GetNativeImageNamed(int resource_id) const {
|
|||||||
return kEmptyImage;
|
return kEmptyImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
bool ContentClient::SandboxPlugin(CommandLine* command_line,
|
|
||||||
sandbox::TargetPolicy* policy) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(OS_MACOSX) && !defined(OS_IOS)
|
#if defined(OS_MACOSX) && !defined(OS_IOS)
|
||||||
bool ContentClient::GetSandboxProfileForSandboxType(
|
bool ContentClient::GetSandboxProfileForSandboxType(
|
||||||
int sandbox_type,
|
int sandbox_type,
|
||||||
|
@@ -126,12 +126,6 @@ class CONTENT_EXPORT ContentClient {
|
|||||||
// Returns a native image given its id.
|
// Returns a native image given its id.
|
||||||
virtual gfx::Image& GetNativeImageNamed(int resource_id) const;
|
virtual gfx::Image& GetNativeImageNamed(int resource_id) const;
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
// Allows the embedder to sandbox a plugin, and apply a custom policy.
|
|
||||||
virtual bool SandboxPlugin(CommandLine* command_line,
|
|
||||||
sandbox::TargetPolicy* policy);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(OS_MACOSX) && !defined(OS_IOS)
|
#if defined(OS_MACOSX) && !defined(OS_IOS)
|
||||||
// Allows the embedder to define a new |sandbox_type| by mapping it to the
|
// Allows the embedder to define a new |sandbox_type| by mapping it to the
|
||||||
// resource ID corresponding to the sandbox profile to use. The legal values
|
// resource ID corresponding to the sandbox profile to use. The legal values
|
||||||
|
@@ -9,7 +9,6 @@ namespace npapi {
|
|||||||
|
|
||||||
const char16 kNativeWindowClassName[] = L"NativeWindowClass";
|
const char16 kNativeWindowClassName[] = L"NativeWindowClass";
|
||||||
const char16 kWrapperNativeWindowClassName[] = L"WrapperNativeWindowClass";
|
const char16 kWrapperNativeWindowClassName[] = L"WrapperNativeWindowClass";
|
||||||
const char16 kNativeWindowClassFilterProp[] = L"NativeWindowClassFilterProp";
|
|
||||||
const char16 kPaintMessageName[] = L"Chrome_CustomPaintil";
|
const char16 kPaintMessageName[] = L"Chrome_CustomPaintil";
|
||||||
const char16 kRegistryMozillaPlugins[] = L"SOFTWARE\\MozillaPlugins";
|
const char16 kRegistryMozillaPlugins[] = L"SOFTWARE\\MozillaPlugins";
|
||||||
const char16 kMozillaActiveXPlugin[] = L"npmozax.dll";
|
const char16 kMozillaActiveXPlugin[] = L"npmozax.dll";
|
||||||
@@ -17,7 +16,6 @@ const char16 kNewWMPPlugin[] = L"np-mswmp.dll";
|
|||||||
const char16 kOldWMPPlugin[] = L"npdsplay.dll";
|
const char16 kOldWMPPlugin[] = L"npdsplay.dll";
|
||||||
const char16 kYahooApplicationStatePlugin[] = L"npystate.dll";
|
const char16 kYahooApplicationStatePlugin[] = L"npystate.dll";
|
||||||
const char16 kWanWangProtocolHandlerPlugin[] = L"npww.dll";
|
const char16 kWanWangProtocolHandlerPlugin[] = L"npww.dll";
|
||||||
const char16 kBuiltinFlashPlugin[] = L"gcswf32.dll";
|
|
||||||
const char16 kFlashPlugin[] = L"npswf32.dll";
|
const char16 kFlashPlugin[] = L"npswf32.dll";
|
||||||
const char16 kAcrobatReaderPlugin[] = L"nppdf32.dll";
|
const char16 kAcrobatReaderPlugin[] = L"nppdf32.dll";
|
||||||
const char16 kRealPlayerPlugin[] = L"nppl3260.dll";
|
const char16 kRealPlayerPlugin[] = L"nppl3260.dll";
|
||||||
|
@@ -18,9 +18,6 @@ namespace npapi {
|
|||||||
// The window class name for a plugin window.
|
// The window class name for a plugin window.
|
||||||
extern const char16 kNativeWindowClassName[];
|
extern const char16 kNativeWindowClassName[];
|
||||||
|
|
||||||
// If property is non-zero window reparenting must add UIPI message filters.
|
|
||||||
WEBKIT_PLUGINS_EXPORT extern const char16 kNativeWindowClassFilterProp[];
|
|
||||||
|
|
||||||
// The name of the window class name for the wrapper HWND around the actual
|
// The name of the window class name for the wrapper HWND around the actual
|
||||||
// plugin window that's used when running in multi-process mode. This window
|
// plugin window that's used when running in multi-process mode. This window
|
||||||
// is created on the browser UI thread.
|
// is created on the browser UI thread.
|
||||||
@@ -38,7 +35,6 @@ WEBKIT_PLUGINS_EXPORT extern const char16 kNewWMPPlugin[];
|
|||||||
extern const char16 kOldWMPPlugin[];
|
extern const char16 kOldWMPPlugin[];
|
||||||
extern const char16 kYahooApplicationStatePlugin[];
|
extern const char16 kYahooApplicationStatePlugin[];
|
||||||
extern const char16 kWanWangProtocolHandlerPlugin[];
|
extern const char16 kWanWangProtocolHandlerPlugin[];
|
||||||
extern const char16 kBuiltinFlashPlugin[];
|
|
||||||
extern const char16 kFlashPlugin[];
|
extern const char16 kFlashPlugin[];
|
||||||
extern const char16 kAcrobatReaderPlugin[];
|
extern const char16 kAcrobatReaderPlugin[];
|
||||||
extern const char16 kRealPlayerPlugin[];
|
extern const char16 kRealPlayerPlugin[];
|
||||||
|
@@ -83,8 +83,6 @@ class WebPlugin {
|
|||||||
// if the plugin enters a modal loop.
|
// if the plugin enters a modal loop.
|
||||||
// Cancels a pending request.
|
// Cancels a pending request.
|
||||||
virtual void SetWindowlessPumpEvent(HANDLE pump_messages_event) = 0;
|
virtual void SetWindowlessPumpEvent(HANDLE pump_messages_event) = 0;
|
||||||
virtual void ReparentPluginWindow(HWND window, HWND parent) = 0;
|
|
||||||
virtual void ReportExecutableMemory(size_t size) = 0;
|
|
||||||
#endif
|
#endif
|
||||||
virtual void CancelResource(unsigned long id) = 0;
|
virtual void CancelResource(unsigned long id) = 0;
|
||||||
virtual void Invalidate() = 0;
|
virtual void Invalidate() = 0;
|
||||||
|
@@ -75,10 +75,7 @@ class WEBKIT_PLUGINS_EXPORT WebPluginDelegateImpl : public WebPluginDelegate {
|
|||||||
PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE = 16384, // Windows
|
PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE = 16384, // Windows
|
||||||
PLUGIN_QUIRK_WINDOWLESS_NO_RIGHT_CLICK = 32768, // Linux
|
PLUGIN_QUIRK_WINDOWLESS_NO_RIGHT_CLICK = 32768, // Linux
|
||||||
PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL = 65536, // Windows.
|
PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL = 65536, // Windows.
|
||||||
PLUGIN_QUIRK_REPARENT_IN_BROWSER = 131072, // Windows
|
PLUGIN_QUIRK_EMULATE_IME = 131072, // Windows.
|
||||||
PLUGIN_QUIRK_PATCH_GETKEYSTATE = 262144, // Windows
|
|
||||||
PLUGIN_QUIRK_EMULATE_IME = 524288, // Windows.
|
|
||||||
PLUGIN_QUIRK_PATCH_VM_API = 1048576, // Windows.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static WebPluginDelegateImpl* Create(const FilePath& filename,
|
static WebPluginDelegateImpl* Create(const FilePath& filename,
|
||||||
@@ -375,7 +372,6 @@ class WEBKIT_PLUGINS_EXPORT WebPluginDelegateImpl : public WebPluginDelegate {
|
|||||||
// receives a WM_LBUTTONDOWN/WM_RBUTTONDOWN message via NPP_HandleEvent.
|
// receives a WM_LBUTTONDOWN/WM_RBUTTONDOWN message via NPP_HandleEvent.
|
||||||
|
|
||||||
HWND dummy_window_for_activation_;
|
HWND dummy_window_for_activation_;
|
||||||
HWND parent_proxy_window_;
|
|
||||||
bool CreateDummyWindowForActivation();
|
bool CreateDummyWindowForActivation();
|
||||||
|
|
||||||
// Returns true if the event passed in needs to be tracked for a potential
|
// Returns true if the event passed in needs to be tracked for a potential
|
||||||
@@ -396,18 +392,6 @@ class WEBKIT_PLUGINS_EXPORT WebPluginDelegateImpl : public WebPluginDelegate {
|
|||||||
// SetCursor interceptor for windowless plugins.
|
// SetCursor interceptor for windowless plugins.
|
||||||
static HCURSOR WINAPI SetCursorPatch(HCURSOR cursor);
|
static HCURSOR WINAPI SetCursorPatch(HCURSOR cursor);
|
||||||
|
|
||||||
// GetKeyStatePatch interceptor for UIPI Flash plugin.
|
|
||||||
static SHORT WINAPI GetKeyStatePatch(int vkey);
|
|
||||||
|
|
||||||
static BOOL WINAPI VirtualProtectPatch(LPVOID address,
|
|
||||||
SIZE_T size,
|
|
||||||
DWORD new_protect,
|
|
||||||
PDWORD old_protect);
|
|
||||||
|
|
||||||
static BOOL WINAPI VirtualFreePatch(LPVOID address,
|
|
||||||
SIZE_T size,
|
|
||||||
DWORD free_type);
|
|
||||||
|
|
||||||
// RegEnumKeyExW interceptor.
|
// RegEnumKeyExW interceptor.
|
||||||
static LONG WINAPI RegEnumKeyExWPatch(
|
static LONG WINAPI RegEnumKeyExWPatch(
|
||||||
HKEY key, DWORD index, LPWSTR name, LPDWORD name_size, LPDWORD reserved,
|
HKEY key, DWORD index, LPWSTR name, LPDWORD name_size, LPDWORD reserved,
|
||||||
|
@@ -92,69 +92,6 @@ base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_reg_enum_key_ex_w =
|
|||||||
base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_get_proc_address =
|
base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_get_proc_address =
|
||||||
LAZY_INSTANCE_INITIALIZER;
|
LAZY_INSTANCE_INITIALIZER;
|
||||||
|
|
||||||
// Helper object for patching the GetKeyState API.
|
|
||||||
base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_get_key_state =
|
|
||||||
LAZY_INSTANCE_INITIALIZER;
|
|
||||||
|
|
||||||
// Saved key state globals and helper access functions.
|
|
||||||
SHORT (WINAPI *g_iat_orig_get_key_state)(int vkey);
|
|
||||||
typedef size_t SavedStateType;
|
|
||||||
const size_t kBitsPerType = sizeof(SavedStateType) * 8;
|
|
||||||
// Bit array of key state corresponding to virtual key index (0=up, 1=down).
|
|
||||||
SavedStateType g_saved_key_state[256 / kBitsPerType];
|
|
||||||
|
|
||||||
bool GetSavedKeyState(WPARAM vkey) {
|
|
||||||
CHECK_LT(vkey, kBitsPerType * sizeof(g_saved_key_state));
|
|
||||||
if (g_saved_key_state[vkey / kBitsPerType] & 1 << (vkey % kBitsPerType))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetSavedKeyState(WPARAM vkey) {
|
|
||||||
CHECK_LT(vkey, kBitsPerType * sizeof(g_saved_key_state));
|
|
||||||
// Cache the key state only for keys blocked by UIPI.
|
|
||||||
if (g_iat_orig_get_key_state(vkey) == 0)
|
|
||||||
g_saved_key_state[vkey / kBitsPerType] |= 1 << (vkey % kBitsPerType);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnsetSavedKeyState(WPARAM vkey) {
|
|
||||||
CHECK_LT(vkey, kBitsPerType * sizeof(g_saved_key_state));
|
|
||||||
g_saved_key_state[vkey / kBitsPerType] &= ~(1 << (vkey % kBitsPerType));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClearSavedKeyState() {
|
|
||||||
memset(g_saved_key_state, 0, sizeof(g_saved_key_state));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper objects for patching VirtualQuery, VirtualProtect.
|
|
||||||
base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_virtual_protect =
|
|
||||||
LAZY_INSTANCE_INITIALIZER;
|
|
||||||
BOOL (WINAPI *g_iat_orig_virtual_protect)(LPVOID address,
|
|
||||||
SIZE_T size,
|
|
||||||
DWORD new_protect,
|
|
||||||
PDWORD old_protect);
|
|
||||||
|
|
||||||
base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_virtual_free =
|
|
||||||
LAZY_INSTANCE_INITIALIZER;
|
|
||||||
BOOL (WINAPI *g_iat_orig_virtual_free)(LPVOID address,
|
|
||||||
SIZE_T size,
|
|
||||||
DWORD free_type);
|
|
||||||
|
|
||||||
const DWORD kExecPageMask = PAGE_EXECUTE_READ;
|
|
||||||
static volatile intptr_t g_max_exec_mem_size;
|
|
||||||
static scoped_ptr<base::Lock> g_exec_mem_lock;
|
|
||||||
|
|
||||||
void UpdateExecMemSize(intptr_t size) {
|
|
||||||
base::AutoLock locked(*g_exec_mem_lock);
|
|
||||||
|
|
||||||
static intptr_t s_exec_mem_size = 0;
|
|
||||||
|
|
||||||
// Floor to zero since shutdown may unmap pages created before our hooks.
|
|
||||||
s_exec_mem_size = std::max(0, s_exec_mem_size + size);
|
|
||||||
if (s_exec_mem_size > g_max_exec_mem_size)
|
|
||||||
g_max_exec_mem_size = s_exec_mem_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// http://crbug.com/16114
|
// http://crbug.com/16114
|
||||||
// Enforces providing a valid device context in NPWindow, so that NPP_SetWindow
|
// Enforces providing a valid device context in NPWindow, so that NPP_SetWindow
|
||||||
// is never called with NPNWindoTypeDrawable and NPWindow set to NULL.
|
// is never called with NPNWindoTypeDrawable and NPWindow set to NULL.
|
||||||
@@ -337,59 +274,6 @@ LRESULT CALLBACK WebPluginDelegateImpl::MouseHookProc(
|
|||||||
return CallNextHookEx(NULL, code, wParam, lParam);
|
return CallNextHookEx(NULL, code, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In addition to the key state we maintain, we also mask in the original
|
|
||||||
// return value. This is done because system keys (e.g. tab, enter, shift)
|
|
||||||
// and toggles (e.g. capslock, numlock) don't ever seem to be blocked.
|
|
||||||
SHORT WINAPI WebPluginDelegateImpl::GetKeyStatePatch(int vkey) {
|
|
||||||
if (GetSavedKeyState(vkey))
|
|
||||||
return g_iat_orig_get_key_state(vkey) | 0x8000;
|
|
||||||
return g_iat_orig_get_key_state(vkey);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to track RX memory usage in plugins to prevent JIT spraying attacks.
|
|
||||||
// This is done by hooking VirtualProtect and VirtualFree.
|
|
||||||
BOOL WINAPI WebPluginDelegateImpl::VirtualProtectPatch(LPVOID address,
|
|
||||||
SIZE_T size,
|
|
||||||
DWORD new_protect,
|
|
||||||
PDWORD old_protect) {
|
|
||||||
if (g_iat_orig_virtual_protect(address, size, new_protect, old_protect)) {
|
|
||||||
bool is_exec = new_protect == kExecPageMask;
|
|
||||||
bool was_exec = *old_protect == kExecPageMask;
|
|
||||||
if (is_exec && !was_exec) {
|
|
||||||
UpdateExecMemSize(static_cast<intptr_t>(size));
|
|
||||||
} else if (!is_exec && was_exec) {
|
|
||||||
UpdateExecMemSize(-(static_cast<intptr_t>(size)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL WINAPI WebPluginDelegateImpl::VirtualFreePatch(LPVOID address,
|
|
||||||
SIZE_T size,
|
|
||||||
DWORD free_type) {
|
|
||||||
MEMORY_BASIC_INFORMATION mem_info;
|
|
||||||
if (::VirtualQuery(address, &mem_info, sizeof(mem_info))) {
|
|
||||||
size_t exec_size = 0;
|
|
||||||
void* base_address = mem_info.AllocationBase;
|
|
||||||
do {
|
|
||||||
if (mem_info.Protect == kExecPageMask)
|
|
||||||
exec_size += mem_info.RegionSize;
|
|
||||||
BYTE* next = reinterpret_cast<BYTE*>(mem_info.BaseAddress) +
|
|
||||||
mem_info.RegionSize;
|
|
||||||
if (!::VirtualQuery(next, &mem_info, sizeof(mem_info)))
|
|
||||||
break;
|
|
||||||
} while (base_address == mem_info.AllocationBase);
|
|
||||||
|
|
||||||
if (exec_size)
|
|
||||||
UpdateExecMemSize(-(static_cast<intptr_t>(exec_size)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return g_iat_orig_virtual_free(address, size, free_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
WebPluginDelegateImpl::WebPluginDelegateImpl(
|
WebPluginDelegateImpl::WebPluginDelegateImpl(
|
||||||
gfx::PluginWindowHandle containing_view,
|
gfx::PluginWindowHandle containing_view,
|
||||||
PluginInstance* instance)
|
PluginInstance* instance)
|
||||||
@@ -404,7 +288,6 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
|
|||||||
last_message_(0),
|
last_message_(0),
|
||||||
is_calling_wndproc(false),
|
is_calling_wndproc(false),
|
||||||
dummy_window_for_activation_(NULL),
|
dummy_window_for_activation_(NULL),
|
||||||
parent_proxy_window_(NULL),
|
|
||||||
handle_event_message_filter_hook_(NULL),
|
handle_event_message_filter_hook_(NULL),
|
||||||
handle_event_pump_messages_event_(NULL),
|
handle_event_pump_messages_event_(NULL),
|
||||||
user_gesture_message_posted_(false),
|
user_gesture_message_posted_(false),
|
||||||
@@ -431,12 +314,6 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
|
|||||||
quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR;
|
quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR;
|
||||||
quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS;
|
quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS;
|
||||||
quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE;
|
quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE;
|
||||||
if (filename == kBuiltinFlashPlugin &&
|
|
||||||
base::win::GetVersion() >= base::win::VERSION_VISTA) {
|
|
||||||
quirks_ |= PLUGIN_QUIRK_REPARENT_IN_BROWSER |
|
|
||||||
PLUGIN_QUIRK_PATCH_GETKEYSTATE |
|
|
||||||
PLUGIN_QUIRK_PATCH_VM_API;
|
|
||||||
}
|
|
||||||
quirks_ |= PLUGIN_QUIRK_EMULATE_IME;
|
quirks_ |= PLUGIN_QUIRK_EMULATE_IME;
|
||||||
} else if (filename == kAcrobatReaderPlugin) {
|
} else if (filename == kAcrobatReaderPlugin) {
|
||||||
// Check for the version number above or equal 9.
|
// Check for the version number above or equal 9.
|
||||||
@@ -493,13 +370,8 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
WebPluginDelegateImpl::~WebPluginDelegateImpl() {
|
WebPluginDelegateImpl::~WebPluginDelegateImpl() {
|
||||||
if (::IsWindow(dummy_window_for_activation_)) {
|
if (::IsWindow(dummy_window_for_activation_))
|
||||||
// Sandboxed Flash stacks two dummy windows to prevent UIPI failures
|
::DestroyWindow(dummy_window_for_activation_);
|
||||||
if (::IsWindow(parent_proxy_window_))
|
|
||||||
::DestroyWindow(parent_proxy_window_);
|
|
||||||
else
|
|
||||||
::DestroyWindow(dummy_window_for_activation_);
|
|
||||||
}
|
|
||||||
|
|
||||||
DestroyInstance();
|
DestroyInstance();
|
||||||
|
|
||||||
@@ -589,37 +461,6 @@ bool WebPluginDelegateImpl::PlatformInitialize() {
|
|||||||
GetProcAddressPatch);
|
GetProcAddressPatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Under UIPI the key state does not get forwarded properly to the child
|
|
||||||
// plugin window. So, instead we track the key state manually and intercept
|
|
||||||
// GetKeyState.
|
|
||||||
if ((quirks_ & PLUGIN_QUIRK_PATCH_GETKEYSTATE) &&
|
|
||||||
!g_iat_patch_get_key_state.Pointer()->is_patched()) {
|
|
||||||
g_iat_orig_get_key_state = ::GetKeyState;
|
|
||||||
g_iat_patch_get_key_state.Pointer()->Patch(
|
|
||||||
L"gcswf32.dll", "user32.dll", "GetKeyState",
|
|
||||||
WebPluginDelegateImpl::GetKeyStatePatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hook the VM calls so we can track the amount of executable memory being
|
|
||||||
// allocated by Flash (and potentially other plugins).
|
|
||||||
if (quirks_ & PLUGIN_QUIRK_PATCH_VM_API) {
|
|
||||||
if (!g_exec_mem_lock.get())
|
|
||||||
g_exec_mem_lock.reset(new base::Lock());
|
|
||||||
|
|
||||||
if (!g_iat_patch_virtual_protect.Pointer()->is_patched()) {
|
|
||||||
g_iat_orig_virtual_protect = ::VirtualProtect;
|
|
||||||
g_iat_patch_virtual_protect.Pointer()->Patch(
|
|
||||||
L"gcswf32.dll", "kernel32.dll", "VirtualProtect",
|
|
||||||
WebPluginDelegateImpl::VirtualProtectPatch);
|
|
||||||
}
|
|
||||||
if (!g_iat_patch_virtual_free.Pointer()->is_patched()) {
|
|
||||||
g_iat_orig_virtual_free = ::VirtualFree;
|
|
||||||
g_iat_patch_virtual_free.Pointer()->Patch(
|
|
||||||
L"gcswf32.dll", "kernel32.dll", "VirtualFree",
|
|
||||||
WebPluginDelegateImpl::VirtualFreePatch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,12 +472,6 @@ void WebPluginDelegateImpl::PlatformDestroyInstance() {
|
|||||||
if (instance_->plugin_lib()->instance_count() != 1)
|
if (instance_->plugin_lib()->instance_count() != 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Pass back the stats for max executable memory.
|
|
||||||
if (quirks_ & PLUGIN_QUIRK_PATCH_VM_API) {
|
|
||||||
plugin_->ReportExecutableMemory(g_max_exec_mem_size);
|
|
||||||
g_max_exec_mem_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_iat_patch_set_cursor.Pointer()->is_patched())
|
if (g_iat_patch_set_cursor.Pointer()->is_patched())
|
||||||
g_iat_patch_set_cursor.Pointer()->Unpatch();
|
g_iat_patch_set_cursor.Pointer()->Unpatch();
|
||||||
|
|
||||||
@@ -666,9 +501,6 @@ bool WebPluginDelegateImpl::WindowedCreatePlugin() {
|
|||||||
|
|
||||||
RegisterNativeWindowClass();
|
RegisterNativeWindowClass();
|
||||||
|
|
||||||
// UIPI requires reparenting in the (medium-integrity) browser process.
|
|
||||||
bool reparent_in_browser = (quirks_ & PLUGIN_QUIRK_REPARENT_IN_BROWSER) != 0;
|
|
||||||
|
|
||||||
// The window will be sized and shown later.
|
// The window will be sized and shown later.
|
||||||
windowed_handle_ = CreateWindowEx(
|
windowed_handle_ = CreateWindowEx(
|
||||||
WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
|
WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
|
||||||
@@ -679,16 +511,14 @@ bool WebPluginDelegateImpl::WindowedCreatePlugin() {
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
reparent_in_browser ? NULL : parent_,
|
parent_,
|
||||||
0,
|
0,
|
||||||
GetModuleHandle(NULL),
|
GetModuleHandle(NULL),
|
||||||
0);
|
0);
|
||||||
if (windowed_handle_ == 0)
|
if (windowed_handle_ == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (reparent_in_browser) {
|
if (IsWindow(parent_)) {
|
||||||
plugin_->ReparentPluginWindow(windowed_handle_, parent_);
|
|
||||||
} else if (IsWindow(parent_)) {
|
|
||||||
// This is a tricky workaround for Issue 2673 in chromium "Flash: IME not
|
// This is a tricky workaround for Issue 2673 in chromium "Flash: IME not
|
||||||
// available". To use IMEs in this window, we have to make Windows attach
|
// available". To use IMEs in this window, we have to make Windows attach
|
||||||
// IMEs to this window (i.e. load IME DLLs, attach them to this process,
|
// IMEs to this window (i.e. load IME DLLs, attach them to this process,
|
||||||
@@ -910,29 +740,6 @@ BOOL CALLBACK EnumFlashWindows(HWND window, LPARAM arg) {
|
|||||||
bool WebPluginDelegateImpl::CreateDummyWindowForActivation() {
|
bool WebPluginDelegateImpl::CreateDummyWindowForActivation() {
|
||||||
DCHECK(!dummy_window_for_activation_);
|
DCHECK(!dummy_window_for_activation_);
|
||||||
|
|
||||||
// Built-in Flash runs with UIPI, but in windowless mode Flash sometimes
|
|
||||||
// tries to attach windows to the parent (which fails under UIPI). To make
|
|
||||||
// it work we add an extra dummy parent in the low-integrity process.
|
|
||||||
if (quirks_ & PLUGIN_QUIRK_REPARENT_IN_BROWSER) {
|
|
||||||
parent_proxy_window_ = CreateWindowEx(
|
|
||||||
0,
|
|
||||||
L"Static",
|
|
||||||
kDummyActivationWindowName,
|
|
||||||
WS_POPUP,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
GetModuleHandle(NULL),
|
|
||||||
0);
|
|
||||||
|
|
||||||
if (parent_proxy_window_ == 0)
|
|
||||||
return false;
|
|
||||||
plugin_->ReparentPluginWindow(parent_proxy_window_, parent_);
|
|
||||||
}
|
|
||||||
|
|
||||||
dummy_window_for_activation_ = CreateWindowEx(
|
dummy_window_for_activation_ = CreateWindowEx(
|
||||||
0,
|
0,
|
||||||
L"Static",
|
L"Static",
|
||||||
@@ -942,7 +749,7 @@ bool WebPluginDelegateImpl::CreateDummyWindowForActivation() {
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
parent_proxy_window_ ? parent_proxy_window_ : parent_,
|
parent_,
|
||||||
0,
|
0,
|
||||||
GetModuleHandle(NULL),
|
GetModuleHandle(NULL),
|
||||||
0);
|
0);
|
||||||
@@ -1133,31 +940,6 @@ LRESULT CALLBACK WebPluginDelegateImpl::NativeWndProc(
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track the keystate to work around a UIPI issue.
|
|
||||||
if (delegate->GetQuirks() & PLUGIN_QUIRK_PATCH_GETKEYSTATE) {
|
|
||||||
switch (message) {
|
|
||||||
case WM_KEYDOWN:
|
|
||||||
SetSavedKeyState(wparam);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_KEYUP:
|
|
||||||
UnsetSavedKeyState(wparam);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Clear out the saved keystate whenever the Flash thread loses focus.
|
|
||||||
case WM_KILLFOCUS:
|
|
||||||
case WM_SETFOCUS:
|
|
||||||
if (::GetCurrentThreadId() != ::GetWindowThreadProcessId(
|
|
||||||
reinterpret_cast<HWND>(wparam), NULL)) {
|
|
||||||
ClearSavedKeyState();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LRESULT result;
|
LRESULT result;
|
||||||
uint32 old_message = delegate->last_message_;
|
uint32 old_message = delegate->last_message_;
|
||||||
delegate->last_message_ = message;
|
delegate->last_message_ = message;
|
||||||
@@ -1324,9 +1106,6 @@ bool WebPluginDelegateImpl::PlatformSetPluginHasFocus(bool focused) {
|
|||||||
focus_event.wParam = 0;
|
focus_event.wParam = 0;
|
||||||
focus_event.lParam = 0;
|
focus_event.lParam = 0;
|
||||||
|
|
||||||
if (GetQuirks() & PLUGIN_QUIRK_PATCH_GETKEYSTATE)
|
|
||||||
ClearSavedKeyState();
|
|
||||||
|
|
||||||
instance()->NPP_HandleEvent(&focus_event);
|
instance()->NPP_HandleEvent(&focus_event);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1446,13 +1225,6 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetQuirks() & PLUGIN_QUIRK_PATCH_GETKEYSTATE) {
|
|
||||||
if (np_event.event == WM_KEYDOWN)
|
|
||||||
SetSavedKeyState(np_event.wParam);
|
|
||||||
else if (np_event.event == WM_KEYUP)
|
|
||||||
UnsetSavedKeyState(np_event.wParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow this plug-in to access this IME emulator through IMM32 API while the
|
// Allow this plug-in to access this IME emulator through IMM32 API while the
|
||||||
// plug-in is processing this event.
|
// plug-in is processing this event.
|
||||||
if (GetQuirks() & PLUGIN_QUIRK_EMULATE_IME) {
|
if (GetQuirks() & PLUGIN_QUIRK_EMULATE_IME) {
|
||||||
|
Reference in New Issue
Block a user