1 // Copyright (c) 2011 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.
8 #include "base/file_util.h"
9 #include "base/path_service.h"
10 #include "base/win/scoped_comptr.h"
11 #include "chrome_frame/test/chrome_frame_test_utils.h"
12 #include "chrome_frame/test/urlmon_moniker_tests.h"
13 #include "chrome_frame/urlmon_bind_status_callback.h"
15 using chrome_frame_test::ScopedVirtualizeHklmAndHkcu
;
16 using testing::Return
;
19 class MonikerPatchTest
: public testing::Test
{
24 virtual void SetUp() {
25 DeleteAllSingletons();
26 PathService::Get(base::DIR_SOURCE_ROOT
, &test_file_path_
);
27 test_file_path_
= test_file_path_
.Append(FILE_PATH_LITERAL("chrome_frame"))
28 .Append(FILE_PATH_LITERAL("test"))
29 .Append(FILE_PATH_LITERAL("data"));
32 bool ReadFileAsString(const wchar_t* file_name
, std::string
* file_contents
) {
33 EXPECT_TRUE(file_name
);
34 base::FilePath file_path
= test_file_path_
.Append(file_name
);
35 return file_util::ReadFileToString(file_path
, file_contents
);
38 static bool StringToStream(const std::string
& data
, IStream
** ret
) {
39 EXPECT_TRUE(!data
.empty());
41 base::win::ScopedComPtr
<IStream
> stream
;
42 HRESULT hr
= CreateStreamOnHGlobal(NULL
, TRUE
, stream
.Receive());
43 EXPECT_HRESULT_SUCCEEDED(hr
);
49 hr
= stream
->Write(data
.c_str(), data
.size(), &written
);
50 EXPECT_HRESULT_SUCCEEDED(hr
);
51 EXPECT_EQ(data
.size(), written
);
56 *ret
= stream
.Detach();
63 base::FilePath test_file_path_
;
64 ScopedVirtualizeHklmAndHkcu virtualized_registry_
;
67 // Tests the CacheStream class by writing content into a stream object
68 // and verify that reading that stream back
69 TEST_F(MonikerPatchTest
, CacheStream
) {
70 const char data
[] = "ReadStreamCacheTest";
71 char ret
[2 * sizeof(data
)] = {0};
74 // Test 1: empty stream reads nothing
75 CComObjectStackEx
<CacheStream
> cache_stream1
;
76 EXPECT_EQ(S_FALSE
, cache_stream1
.Read(ret
, sizeof(ret
), &read
));
79 // Test 2: Read from initialized cache
80 CComObjectStackEx
<CacheStream
> cache_stream2
;
81 cache_stream2
.Initialize(data
, sizeof(data
), false);
82 EXPECT_HRESULT_SUCCEEDED(cache_stream2
.Read(ret
, sizeof(ret
), &read
));
83 EXPECT_EQ(sizeof(data
), read
);
84 EXPECT_EQ(std::string(data
), std::string(ret
));
87 EXPECT_EQ(E_PENDING
, cache_stream2
.Read(ret
, sizeof(ret
), &read
));
91 ACTION_P3(ReadStream
, buffer
, size
, ret
) {
92 EXPECT_EQ(TYMED_ISTREAM
, arg3
->tymed
);
93 *ret
= arg3
->pstm
->Read(buffer
, *size
, size
);
96 // Tests the implementation of BSCBFeedData to feed data to the
97 // specified IBindStatusCallback
98 TEST_F(MonikerPatchTest
, BSCBFeedData
) {
99 CComObjectStackEx
<MockBindStatusCallbackImpl
> mock
;
100 const char data
[] = "ReadStreamCacheTest";
101 const DWORD size
= sizeof(data
);
102 const CLIPFORMAT cf
= 0xd0d0;
103 const DWORD flags
= BSCF_FIRSTDATANOTIFICATION
| BSCF_LASTDATANOTIFICATION
;
104 const DWORD kArbitraryreadSize
= 0xdeadbabe;
106 char read_buffer1
[size
] = {0}, read_buffer2
[size
] = {0};
107 DWORD read_size1
= size
, read_size2
= kArbitraryreadSize
;
108 HRESULT ret1
= E_FAIL
, ret2
= E_FAIL
;
110 EXPECT_CALL(mock
, OnDataAvailable(flags
, size
,
111 testing::Field(&FORMATETC::cfFormat
, cf
),
112 testing::Field(&STGMEDIUM::tymed
, TYMED_ISTREAM
)))
113 .WillOnce(testing::DoAll(
114 ReadStream(read_buffer1
, &read_size1
, &ret1
),
115 ReadStream(read_buffer2
, &read_size2
, &ret2
),
118 EXPECT_HRESULT_SUCCEEDED(CacheStream::BSCBFeedData(&mock
, data
, size
, cf
,
121 EXPECT_HRESULT_SUCCEEDED(ret1
);
122 EXPECT_STREQ(data
, read_buffer1
);
123 EXPECT_EQ(size
, read_size1
);
125 EXPECT_EQ(E_PENDING
, ret2
);
126 EXPECT_STREQ("", read_buffer2
);
127 EXPECT_EQ(kArbitraryreadSize
, read_size2
);
130 const wchar_t kSmallHtmlMetaTag
[] = L
"sub_frame1.html";
131 const wchar_t kSmallHtmlNoMetaTag
[] = L
"host_browser.html";
133 // Test various aspects of the SniffData class
134 TEST_F(MonikerPatchTest
, SniffDataMetaTag
) {
135 std::string small_html_meta_tag
, small_html_no_meta_tag
;
136 ASSERT_TRUE(ReadFileAsString(kSmallHtmlMetaTag
, &small_html_meta_tag
));
137 ASSERT_TRUE(ReadFileAsString(kSmallHtmlNoMetaTag
, &small_html_no_meta_tag
));
139 base::win::ScopedComPtr
<IStream
> stream_with_meta
, stream_no_meta
;
140 ASSERT_TRUE(StringToStream(small_html_meta_tag
, stream_with_meta
.Receive()));
141 ASSERT_TRUE(StringToStream(small_html_no_meta_tag
,
142 stream_no_meta
.Receive()));
144 // Initialize 2 sniffers 1 with meta tag and 1 without.
145 SniffData sniffer1
, sniffer2
;
146 EXPECT_HRESULT_SUCCEEDED(sniffer1
.InitializeCache(std::wstring()));
147 EXPECT_HRESULT_SUCCEEDED(sniffer2
.InitializeCache(std::wstring()));
148 EXPECT_HRESULT_SUCCEEDED(sniffer1
.ReadIntoCache(stream_with_meta
, true));
149 EXPECT_HRESULT_SUCCEEDED(sniffer2
.ReadIntoCache(stream_no_meta
, true));
151 // Verify renderer type and size read.
152 EXPECT_TRUE(sniffer1
.is_chrome());
153 EXPECT_EQ(SniffData::OTHER
, sniffer2
.renderer_type());
154 EXPECT_EQ(small_html_meta_tag
.size(), sniffer1
.size());
155 EXPECT_EQ(small_html_no_meta_tag
.size(), sniffer2
.size());
158 // Now test how the data is fed back the the bind status callback.
159 // case 1: callback reads data in 1 read
160 TEST_F(MonikerPatchTest
, SniffDataPlayback1
) {
161 std::string small_html_meta_tag
;
162 base::win::ScopedComPtr
<IStream
> stream_with_meta
;
165 EXPECT_HRESULT_SUCCEEDED(sniffer
.InitializeCache(std::wstring()));
166 ASSERT_TRUE(ReadFileAsString(kSmallHtmlMetaTag
, &small_html_meta_tag
));
167 ASSERT_TRUE(StringToStream(small_html_meta_tag
, stream_with_meta
.Receive()));
168 EXPECT_HRESULT_SUCCEEDED(sniffer
.ReadIntoCache(stream_with_meta
, true));
170 CComObjectStackEx
<MockBindStatusCallbackImpl
> mock
;
171 const CLIPFORMAT cf
= 0xd0d0;
172 const DWORD flags
= BSCF_FIRSTDATANOTIFICATION
| BSCF_LASTDATANOTIFICATION
;
173 const DWORD data_size
= small_html_meta_tag
.size();
175 DWORD read_size1
= data_size
* 2;
176 scoped_ptr
<char[]> read_buffer1(new char[read_size1
]);
177 ZeroMemory(read_buffer1
.get(), read_size1
);
179 char read_buffer2
[10] = {0};
180 DWORD read_size2
= sizeof(read_buffer2
);
181 HRESULT ret1
= E_FAIL
, ret2
= E_FAIL
;
183 EXPECT_CALL(mock
, OnDataAvailable(flags
, data_size
,
184 testing::Field(&FORMATETC::cfFormat
, cf
),
185 testing::Field(&STGMEDIUM::tymed
, TYMED_ISTREAM
)))
186 .WillOnce(testing::DoAll(
187 ReadStream(read_buffer1
.get(), &read_size1
, &ret1
),
188 ReadStream(read_buffer2
, &read_size2
, &ret2
),
191 EXPECT_HRESULT_SUCCEEDED(sniffer
.DrainCache(&mock
, flags
, cf
));
193 EXPECT_HRESULT_SUCCEEDED(ret1
);
194 EXPECT_EQ(small_html_meta_tag
, read_buffer1
.get());
195 EXPECT_EQ(data_size
, read_size1
);
197 EXPECT_EQ(S_FALSE
, ret2
);
198 EXPECT_STREQ("", read_buffer2
);
199 EXPECT_EQ(sizeof(read_buffer2
), read_size2
);
202 // case 2: callback reads data in 2 reads.
203 TEST_F(MonikerPatchTest
, SniffDataPlayback2
) {
204 std::string small_html_meta_tag
;
205 base::win::ScopedComPtr
<IStream
> stream_with_meta
;
208 EXPECT_HRESULT_SUCCEEDED(sniffer
.InitializeCache(std::wstring()));
209 ASSERT_TRUE(ReadFileAsString(kSmallHtmlMetaTag
, &small_html_meta_tag
));
210 ASSERT_TRUE(StringToStream(small_html_meta_tag
, stream_with_meta
.Receive()));
211 EXPECT_HRESULT_SUCCEEDED(sniffer
.ReadIntoCache(stream_with_meta
, true));
213 CComObjectStackEx
<MockBindStatusCallbackImpl
> mock
;
214 const CLIPFORMAT cf
= 0xd0d0;
215 const DWORD flags
= BSCF_FIRSTDATANOTIFICATION
| BSCF_LASTDATANOTIFICATION
;
216 const DWORD data_size
= small_html_meta_tag
.size();
218 DWORD read_size1
= data_size
/ 2; // First read is half the data.
219 DWORD read_size2
= data_size
; // Second read, try to read past data.
220 scoped_ptr
<char[]> read_buffer1(new char[read_size1
]);
221 scoped_ptr
<char[]> read_buffer2(new char[read_size2
]);
222 ZeroMemory(read_buffer1
.get(), read_size1
);
223 ZeroMemory(read_buffer2
.get(), read_size2
);
225 char read_buffer3
[10] = {0};
226 DWORD read_size3
= sizeof(read_buffer3
);
227 HRESULT ret1
= E_FAIL
, ret2
= E_FAIL
, ret3
= E_FAIL
;
229 EXPECT_CALL(mock
, OnDataAvailable(flags
, data_size
,
230 testing::Field(&FORMATETC::cfFormat
, cf
),
231 testing::Field(&STGMEDIUM::tymed
, TYMED_ISTREAM
)))
232 .WillOnce(testing::DoAll(
233 ReadStream(read_buffer1
.get(), &read_size1
, &ret1
),
234 ReadStream(read_buffer2
.get(), &read_size2
, &ret2
),
235 ReadStream(read_buffer3
, &read_size3
, &ret3
),
238 EXPECT_HRESULT_SUCCEEDED(sniffer
.DrainCache(&mock
, flags
, cf
));
240 EXPECT_HRESULT_SUCCEEDED(ret1
);
241 EXPECT_HRESULT_SUCCEEDED(ret2
);
242 EXPECT_EQ(data_size
/2, read_size1
);
243 EXPECT_EQ(data_size
- read_size1
, read_size2
);
245 std::string data_read
;
246 data_read
.append(read_buffer1
.get(), read_size1
);
247 data_read
.append(read_buffer2
.get(), read_size2
);
248 EXPECT_EQ(small_html_meta_tag
, data_read
);
250 EXPECT_EQ(S_FALSE
, ret3
);
251 EXPECT_STREQ("", read_buffer3
);
252 EXPECT_EQ(sizeof(read_buffer3
), read_size3
);