| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2010 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/profiles/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.value().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 = CommandLine::FromString(cmd_line); | |
| 103 std::string channel_id = parsed_command_line.GetSwitchValueASCII( | |
| 104 switches::kAutomationClientChannelID); | |
| 105 EXPECT_FALSE(channel_id.empty()); | |
| 106 | |
| 107 delegate_->OnConnectAutomationProviderToChannel(channel_id); | |
| 108 } | |
| 109 return TRUE; | |
| 110 } | |
| OLD | NEW |