OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome_frame/test/net/process_singleton_subclass.h" |
| 6 |
| 7 #include "base/command_line.h" |
| 8 #include "base/path_service.h" |
| 9 #include "base/string_util.h" |
| 10 #include "chrome/browser/browser_process_impl.h" |
| 11 #include "chrome/browser/profile_manager.h" |
| 12 #include "chrome/common/chrome_constants.h" |
| 13 #include "chrome/common/chrome_paths.h" |
| 14 #include "chrome/common/chrome_switches.h" |
| 15 #include "chrome_frame/test/net/test_automation_provider.h" |
| 16 #include "chrome_frame/function_stub.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 |
| 19 ProcessSingletonSubclass::ProcessSingletonSubclass( |
| 20 ProcessSingletonSubclassDelegate* delegate) |
| 21 : stub_(NULL), delegate_(delegate), original_wndproc_(NULL) { |
| 22 } |
| 23 |
| 24 ProcessSingletonSubclass::~ProcessSingletonSubclass() { |
| 25 if (stub_) { |
| 26 stub_->BypassStub(reinterpret_cast<void*>(original_wndproc_)); |
| 27 } |
| 28 } |
| 29 |
| 30 bool ProcessSingletonSubclass::Subclass(const FilePath& user_data_dir) { |
| 31 DCHECK(stub_ == NULL); |
| 32 DCHECK(original_wndproc_ == NULL); |
| 33 HWND hwnd = FindWindowEx(HWND_MESSAGE, NULL, chrome::kMessageWindowClass, |
| 34 user_data_dir.ToWStringHack().c_str()); |
| 35 if (!::IsWindow(hwnd)) |
| 36 return false; |
| 37 |
| 38 // The window must be in this process for us to be able to subclass it. |
| 39 DWORD pid = 0; |
| 40 ::GetWindowThreadProcessId(hwnd, &pid); |
| 41 EXPECT_EQ(pid, ::GetCurrentProcessId()); |
| 42 |
| 43 original_wndproc_ = reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hwnd, |
| 44 GWLP_WNDPROC)); |
| 45 stub_ = FunctionStub::Create(reinterpret_cast<uintptr_t>(this), |
| 46 &SubclassWndProc); |
| 47 DCHECK(stub_); |
| 48 ::SetWindowLongPtr(hwnd, GWLP_WNDPROC, |
| 49 reinterpret_cast<LONG_PTR>(stub_->code())); |
| 50 return true; |
| 51 } |
| 52 |
| 53 // static |
| 54 LRESULT ProcessSingletonSubclass::SubclassWndProc(ProcessSingletonSubclass* me, |
| 55 HWND hwnd, UINT msg, |
| 56 WPARAM wp, LPARAM lp) { |
| 57 switch (msg) { |
| 58 case WM_COPYDATA: |
| 59 return me->OnCopyData(hwnd, reinterpret_cast<HWND>(wp), |
| 60 reinterpret_cast<COPYDATASTRUCT*>(lp)); |
| 61 default: |
| 62 break; |
| 63 } |
| 64 |
| 65 return me->original_wndproc_(hwnd, msg, wp, lp); |
| 66 } |
| 67 |
| 68 // static |
| 69 LRESULT ProcessSingletonSubclass::OnCopyData(HWND hwnd, HWND from_hwnd, |
| 70 const COPYDATASTRUCT* cds) { |
| 71 // We should have enough room for the shortest command (min_message_size) |
| 72 // and also be a multiple of wchar_t bytes. The shortest command |
| 73 // possible is L"START\0\0" (empty current directory and command line). |
| 74 static const int kMinMessageSize = sizeof(L"START\0"); |
| 75 EXPECT_TRUE(kMinMessageSize <= cds->cbData); |
| 76 |
| 77 if (kMinMessageSize > cds->cbData) |
| 78 return TRUE; |
| 79 |
| 80 // We split the string into 4 parts on NULLs. |
| 81 const wchar_t* begin = reinterpret_cast<const wchar_t*>(cds->lpData); |
| 82 const wchar_t* end = begin + (cds->cbData / sizeof(wchar_t)); |
| 83 const wchar_t kNull = L'\0'; |
| 84 const wchar_t* eos = wmemchr(begin, kNull, end - begin); |
| 85 EXPECT_NE(eos, end); |
| 86 if (lstrcmpW(begin, L"START") == 0) { |
| 87 begin = eos + 1; |
| 88 EXPECT_TRUE(begin <= end); |
| 89 eos = wmemchr(begin, kNull, end - begin); |
| 90 EXPECT_NE(eos, end); |
| 91 |
| 92 // Get current directory. |
| 93 const wchar_t* cur_dir = begin; |
| 94 begin = eos + 1; |
| 95 EXPECT_TRUE(begin <= end); |
| 96 eos = wmemchr(begin, kNull, end - begin); |
| 97 // eos might be equal to end at this point. |
| 98 |
| 99 // Get command line. |
| 100 std::wstring cmd_line(begin, static_cast<size_t>(end - begin)); |
| 101 |
| 102 CommandLine parsed_command_line(L""); |
| 103 parsed_command_line.ParseFromString(cmd_line); |
| 104 std::string channel_id(WideToASCII(parsed_command_line.GetSwitchValue( |
| 105 switches::kAutomationClientChannelID))); |
| 106 EXPECT_FALSE(channel_id.empty()); |
| 107 |
| 108 delegate_->OnConnectAutomationProviderToChannel(channel_id); |
| 109 } |
| 110 return TRUE; |
| 111 } |
OLD | NEW |