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

Side by Side Diff: chrome/browser/rlz/rlz_unittest.cc

Issue 7736001: Adding unit tests to RLZ code. Refactoring RLZ code to make it more testable. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Taking out dependence on PageTransition::HOME_PAGE. Will fix once home page feature is implemented Created 9 years, 4 months 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
« chrome/browser/rlz/rlz.cc ('K') | « chrome/browser/rlz/rlz.cc ('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 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/rlz/rlz.h" 5 #include "chrome/browser/rlz/rlz.h"
6 6
7 #include "base/memory/scoped_ptr.h"
8 #include "base/stringprintf.h"
7 #include "base/path_service.h" 9 #include "base/path_service.h"
10 #include "base/test/test_reg_util_win.h"
11 #include "base/utf_string_conversions.h"
8 #include "base/win/registry.h" 12 #include "base/win/registry.h"
13 #include "chrome/browser/autocomplete/autocomplete.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/rlz/rlz.h"
16 #include "chrome/common/chrome_notification_types.h"
17 #include "chrome/common/env_vars.h"
18 #include "chrome/test/base/testing_browser_process_test.h"
19 #include "content/browser/tab_contents/navigation_entry.h"
20 #include "content/common/notification_details.h"
21 #include "content/common/notification_source.h"
9 #include "testing/gtest/include/gtest/gtest.h" 22 #include "testing/gtest/include/gtest/gtest.h"
10 23
11 using base::win::RegKey; 24 using base::win::RegKey;
25 using registry_util::RegistryOverrideManager;
26 using testing::AssertionResult;
27 using testing::AssertionSuccess;
28 using testing::AssertionFailure;
12 29
13 namespace { 30 namespace {
14 31
15 // Gets rid of registry leftovers from testing. Returns false if there 32 // Registry path to overridden hive.
16 // is nothing to clean. 33 const wchar_t kRlzTempHkcu[] = L"rlz_hkcu";
17 bool CleanValue(const wchar_t* key_name, const wchar_t* value) { 34 const wchar_t kRlzTempHklm[] = L"rlz_hklm";
18 RegKey key; 35
19 if (key.Open(HKEY_CURRENT_USER, key_name, KEY_READ | KEY_WRITE) != 36 // Dummy RLZ string for the access points.
20 ERROR_SUCCESS) 37 const char kOmniboxRlzString[] = "test_omnibox";
21 return false; 38 const char kHomepageRlzString[] = "test_homepage";
22 EXPECT_EQ(ERROR_SUCCESS, key.DeleteValue(value)); 39
23 return true; 40 // Some helper macros to test it a string contains/does not contain a substring.
24 } 41
25 42 AssertionResult CmpHelperSTRC(const char* str_expression,
26 // The chrome events RLZ key lives here. 43 const char* substr_expression,
27 const wchar_t kKeyName[] = L"Software\\Google\\Common\\Rlz\\Events\\C"; 44 const char* str,
45 const char* substr) {
46 if (NULL != strstr(str, substr)) {
47 return AssertionSuccess();
48 }
49
50 return AssertionFailure() << "Expected: (" << substr_expression << ") in ("
51 << str_expression << "), actual: '"
52 << substr << "' not in '" << str << "'";
53 }
54
55 AssertionResult CmpHelperSTRNC(const char* str_expression,
56 const char* substr_expression,
57 const char* str,
58 const char* substr) {
59 if (NULL == strstr(str, substr)) {
60 return AssertionSuccess();
61 }
62
63 return AssertionFailure() << "Expected: (" << substr_expression
64 << ") not in (" << str_expression << "), actual: '"
65 << substr << "' in '" << str << "'";
66 }
67
68 #define EXPECT_STR_CONTAINS(str, substr) \
69 EXPECT_PRED_FORMAT2(CmpHelperSTRC, str, substr)
70
71 #define EXPECT_STR_NOT_CONTAIN(str, substr) \
72 EXPECT_PRED_FORMAT2(CmpHelperSTRNC, str, substr)
28 73
29 } // namespace 74 } // namespace
30 75
31 TEST(RlzLibTest, RecordProductEvent) { 76 // Test class for RLZ tracker. Makes some member functions public and
32 DWORD recorded_value = 0; 77 // overrides others to make it easier to test.
33 EXPECT_TRUE(RLZTracker::RecordProductEvent(rlz_lib::CHROME, 78 class TestRLZTracker : public RLZTracker {
34 rlz_lib::CHROME_OMNIBOX, rlz_lib::FIRST_SEARCH)); 79 public:
35 const wchar_t kEvent1[] = L"C1F"; 80 using RLZTracker::DelayedInit;
36 RegKey key1; 81 using RLZTracker::Observe;
37 EXPECT_EQ(ERROR_SUCCESS, key1.Open(HKEY_CURRENT_USER, kKeyName, KEY_READ)); 82 using RLZTracker::RLZ_PAGETRANSITION_HOME_PAGE;
38 EXPECT_EQ(ERROR_SUCCESS, key1.ReadValueDW(kEvent1, &recorded_value)); 83
39 EXPECT_EQ(1, recorded_value); 84 TestRLZTracker() : pingnow_called_(false), assume_io_thread_(false) {
40 EXPECT_TRUE(CleanValue(kKeyName, kEvent1)); 85 set_tracker(this);
41 86 }
42 EXPECT_TRUE(RLZTracker::RecordProductEvent(rlz_lib::CHROME, 87
43 rlz_lib::CHROME_HOME_PAGE, rlz_lib::SET_TO_GOOGLE)); 88 virtual ~TestRLZTracker() {
44 const wchar_t kEvent2[] = L"C2S"; 89 set_tracker(NULL);
45 RegKey key2; 90 }
46 EXPECT_EQ(ERROR_SUCCESS, key2.Open(HKEY_CURRENT_USER, kKeyName, KEY_READ)); 91
47 DWORD value = 0; 92 bool pingnow_called() {
48 EXPECT_EQ(ERROR_SUCCESS, key2.ReadValueDW(kEvent2, &recorded_value)); 93 return pingnow_called_;
49 EXPECT_EQ(1, recorded_value); 94 }
50 EXPECT_TRUE(CleanValue(kKeyName, kEvent2)); 95
51 } 96 bool assume_io_thread() {
97 return assume_io_thread_;
98 }
99
100 void set_assume_io_thread(bool assume_io_thread) {
101 assume_io_thread_ = assume_io_thread;
102 }
103
104 private:
105 virtual void ScheduleDelayedInit(int delay) OVERRIDE {
106 // If the delay is 0, invoke the delayed init now. Otherwise,
107 // don't schedule anything, it will be manually called during tests.
108 if (delay == 0)
109 DelayedInit();
110 }
111
112 virtual void ScheduleFinancialPing() OVERRIDE {
113 PingNow(this);
114 }
115
116 virtual bool ScheduleGetAccessPointRlz(rlz_lib::AccessPoint point) OVERRIDE {
117 return !assume_io_thread_;
118 }
119
120 virtual bool SendFinancialPing(const std::wstring& brand,
121 const std::wstring& lang,
122 const std::wstring& referral,
123 bool exclude_id) OVERRIDE {
124 // Don't ping the server during tests.
125 pingnow_called_ = true;
126 return true;
127 }
128
129 bool pingnow_called_;
130 bool assume_io_thread_;
131
132 DISALLOW_COPY_AND_ASSIGN(TestRLZTracker);
133 };
134
135 class RlzLibTest : public TestingBrowserProcessTest {
136 virtual void SetUp() OVERRIDE;
137 virtual void TearDown() OVERRIDE;
138
139 protected:
140 RlzLibTest();
141 ~RlzLibTest();
142
143 void SimulateOmniboxUsage();
144 void SimulateHomepageUsage();
145 void InvokeDelayedInit();
146
147 void ExpectEventRecorded(const char* event_name, bool expected);
148 void ExpectRlzPingSent(bool expected);
149
150 TestRLZTracker tracker_;
151 RegistryOverrideManager override_manager_;
152 wchar_t env_var_[64];
153 };
154
155 RlzLibTest::RlzLibTest() {
156 }
157
158 RlzLibTest::~RlzLibTest() {
159 }
160
161 void RlzLibTest::SetUp() {
162 TestingBrowserProcessTest::SetUp();
163
164 // Make sure HEADLESS environment variable is not set.
165 env_var_[0] = 0;
166 DWORD size = ::GetEnvironmentVariableW(
167 ASCIIToWide(env_vars::kHeadless).c_str(), env_var_, arraysize(env_var_));
168 if (size == 0)
169 ASSERT_EQ(ERROR_ENVVAR_NOT_FOUND, ::GetLastError());
170 ASSERT_LT(size, arraysize(env_var_));
171
172 ::SetEnvironmentVariable(ASCIIToWide(env_vars::kHeadless).c_str(), NULL);
173
174 // Before overriding HKLM for the tests, we need to set it up correctly
175 // so that the rlz_lib calls work. This needs to be done before we do the
176 // override.
177
178 std::wstring temp_hklm_path = base::StringPrintf(
179 L"%ls\\%ls",
180 RegistryOverrideManager::kTempTestKeyPath,
181 kRlzTempHklm);
182
183 base::win::RegKey hklm;
184 ASSERT_EQ(ERROR_SUCCESS, hklm.Create(HKEY_CURRENT_USER,
185 temp_hklm_path.c_str(),
186 KEY_READ));
187
188 std::wstring temp_hkcu_path = base::StringPrintf(
189 L"%ls\\%ls",
190 RegistryOverrideManager::kTempTestKeyPath,
191 kRlzTempHkcu);
192
193 base::win::RegKey hkcu;
194 ASSERT_EQ(ERROR_SUCCESS, hkcu.Create(HKEY_CURRENT_USER,
195 temp_hkcu_path.c_str(),
196 KEY_READ));
197
198 rlz_lib::InitializeTempHivesForTesting(hklm, hkcu);
199
200 // Its important to override HKLM before HKCU because of the registry
201 // initialization performed above.
202 override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE, kRlzTempHklm);
203 override_manager_.OverrideRegistry(HKEY_CURRENT_USER, kRlzTempHkcu);
204 }
205
206 void RlzLibTest::TearDown() {
207 TestingBrowserProcessTest::TearDown();
208
209 if (env_var_[0] != 0)
210 ::SetEnvironmentVariable(ASCIIToWide(env_vars::kHeadless).c_str(),
211 env_var_);
212 }
213
214 void RlzLibTest::SimulateOmniboxUsage() {
215 tracker_.Observe(chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
216 NotificationService::AllSources(),
217 Details<AutocompleteLog>(NULL));
218 }
219
220 void RlzLibTest::SimulateHomepageUsage() {
221 NavigationEntry entry(NULL, 0, GURL(), GURL(), string16(),
222 TestRLZTracker::RLZ_PAGETRANSITION_HOME_PAGE);
223 tracker_.Observe(content::NOTIFICATION_NAV_ENTRY_PENDING,
224 NotificationService::AllSources(),
225 Details<NavigationEntry>(&entry));
226 }
227
228 void RlzLibTest::InvokeDelayedInit() {
229 tracker_.DelayedInit();
230 }
231
232 void RlzLibTest::ExpectEventRecorded(const char* event_name, bool expected) {
233 char cgi[rlz_lib::kMaxCgiLength];
234 GetProductEventsAsCgi(rlz_lib::CHROME, cgi, arraysize(cgi));
235 if (expected) {
236 EXPECT_STR_CONTAINS(cgi, event_name);
237 } else {
238 EXPECT_STR_NOT_CONTAIN(cgi, event_name);
239 }
240 }
241
242 void RlzLibTest::ExpectRlzPingSent(bool expected) {
243 EXPECT_EQ(expected, tracker_.pingnow_called());
244 }
245
246 TEST_F(RlzLibTest, RecordProductEvent) {
247 RLZTracker::RecordProductEvent(rlz_lib::CHROME, rlz_lib::CHROME_OMNIBOX,
248 rlz_lib::FIRST_SEARCH);
249
250 ExpectEventRecorded("C1F", true);
251 }
252
253 // The events that affect the different RLZ scenarios are the following:
254 //
255 // A: the user starts chrome for the first time
256 // B: the user stops chrome
257 // C: the user start a subsequent time
258 // D: the user stops chrome again
259 // I: the RLZTracker::DelayedInit() method is invoked
260 // X: the user performs a search using the omnibox
261 // Y: the user performs a search using the home page
262 //
263 // The events A to D happen in chronological order, but the other events
264 // may happen at any point between A-B or C-D, in no particular order.
265 //
266 // The visible results of the scenarios are:
267 //
268 // C1I event is recorded
269 // C2I event is recorded
270 // C1F event is recorded
271 // C2F event is recorded
272 // C1S event is recorded
273 // C2S event is recorded
274 // RLZ ping sent
275 //
276 // Variations on the above scenarios:
277 //
278 // - if the delay specified to InitRlzDelayed() is negative, then the RLZ
279 // ping should be sent out at the time of event X and not wait for I
280 //
281 // Also want to test that pre-warming the RLZ string cache works correctly.
282
283 TEST_F(RlzLibTest, QuickStopAfterStart) {
284 RLZTracker::InitRlzDelayed(true, 20, true, true);
285
286 // Omnibox events.
287 ExpectEventRecorded("C1I", false);
288 ExpectEventRecorded("C1S", false);
289 ExpectEventRecorded("C1F", false);
290
291 // Home page events.
292 ExpectEventRecorded("C2I", false);
293 ExpectEventRecorded("C2S", false);
294 ExpectEventRecorded("C2F", false);
295
296 ExpectRlzPingSent(false);
297 }
298
299 TEST_F(RlzLibTest, DelayedInitOnly) {
300 RLZTracker::InitRlzDelayed(true, 20, true, true);
301 InvokeDelayedInit();
302
303 // Omnibox events.
304 ExpectEventRecorded("C1I", true);
305 ExpectEventRecorded("C1S", true);
306 ExpectEventRecorded("C1F", false);
307
308 // Home page events.
309 ExpectEventRecorded("C2I", true);
310 ExpectEventRecorded("C2S", true);
311 ExpectEventRecorded("C2F", false);
312
313 ExpectRlzPingSent(true);
314 }
315
316 TEST_F(RlzLibTest, DelayedInitOnlyNoFirstRunNoRlzStrings) {
317 RLZTracker::InitRlzDelayed(false, 20, true, true);
318 InvokeDelayedInit();
319
320 // Omnibox events.
321 ExpectEventRecorded("C1I", true);
322 ExpectEventRecorded("C1S", true);
323 ExpectEventRecorded("C1F", false);
324
325 // Home page events.
326 ExpectEventRecorded("C2I", true);
327 ExpectEventRecorded("C2S", true);
328 ExpectEventRecorded("C2F", false);
329
330 ExpectRlzPingSent(true);
331 }
332
333 TEST_F(RlzLibTest, DelayedInitOnlyNoFirstRun) {
334 // Set some dummy RLZ strings to simulate that we already ran before and
335 // performed a successful ping to the RLZ server.
336 rlz_lib::SetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, kOmniboxRlzString);
337 rlz_lib::SetAccessPointRlz(rlz_lib::CHROME_HOME_PAGE, kHomepageRlzString);
338
339 RLZTracker::InitRlzDelayed(false, 20, true, true);
340 InvokeDelayedInit();
341
342 // Omnibox events.
343 ExpectEventRecorded("C1I", true);
344 ExpectEventRecorded("C1S", false);
345 ExpectEventRecorded("C1F", false);
346
347 // Home page events.
348 ExpectEventRecorded("C2I", true);
349 ExpectEventRecorded("C2S", false);
350 ExpectEventRecorded("C2F", false);
351
352 ExpectRlzPingSent(true);
353 }
354
355 TEST_F(RlzLibTest, DelayedInitOnlyNoGoogleDefaultSearchOrHomepage) {
356 RLZTracker::InitRlzDelayed(true, 20, false, false);
357 InvokeDelayedInit();
358
359 // Omnibox events.
360 ExpectEventRecorded("C1I", true);
361 ExpectEventRecorded("C1S", false);
362 ExpectEventRecorded("C1F", false);
363
364 // Home page events.
365 ExpectEventRecorded("C2I", true);
366 ExpectEventRecorded("C2S", false);
367 ExpectEventRecorded("C2F", false);
368
369 ExpectRlzPingSent(true);
370 }
371
372 TEST_F(RlzLibTest, OmniboxUsageOnly) {
373 RLZTracker::InitRlzDelayed(true, 20, true, true);
374 SimulateOmniboxUsage();
375
376 // Omnibox events.
377 ExpectEventRecorded("C1I", false);
378 ExpectEventRecorded("C1S", false);
379 ExpectEventRecorded("C1F", true);
380
381 // Home page events.
382 ExpectEventRecorded("C2I", false);
383 ExpectEventRecorded("C2S", false);
384 ExpectEventRecorded("C2F", false);
385
386 ExpectRlzPingSent(false);
387 }
388
389 TEST_F(RlzLibTest, HomepageUsageOnly) {
390 RLZTracker::InitRlzDelayed(true, 20, true, true);
391 SimulateHomepageUsage();
392
393 // Omnibox events.
394 ExpectEventRecorded("C1I", false);
395 ExpectEventRecorded("C1S", false);
396 ExpectEventRecorded("C1F", false);
397
398 // Home page events.
399 ExpectEventRecorded("C2I", false);
400 ExpectEventRecorded("C2S", false);
401 ExpectEventRecorded("C2F", true);
402
403 ExpectRlzPingSent(false);
404 }
405
406 TEST_F(RlzLibTest, UsageBeforeDelayedInit) {
407 RLZTracker::InitRlzDelayed(true, 20, true, true);
408 SimulateOmniboxUsage();
409 SimulateHomepageUsage();
410 InvokeDelayedInit();
411
412 // Omnibox events.
413 ExpectEventRecorded("C1I", true);
414 ExpectEventRecorded("C1S", true);
415 ExpectEventRecorded("C1F", true);
416
417 // Home page events.
418 ExpectEventRecorded("C2I", true);
419 ExpectEventRecorded("C2S", true);
420 ExpectEventRecorded("C2F", true);
421
422 ExpectRlzPingSent(true);
423 }
424
425 TEST_F(RlzLibTest, OmniboxUsageAfterDelayedInit) {
426 RLZTracker::InitRlzDelayed(true, 20, true, true);
427 InvokeDelayedInit();
428 SimulateOmniboxUsage();
429 SimulateHomepageUsage();
430
431 // Omnibox events.
432 ExpectEventRecorded("C1I", true);
433 ExpectEventRecorded("C1S", true);
434 ExpectEventRecorded("C1F", true);
435
436 // Home page events.
437 ExpectEventRecorded("C2I", true);
438 ExpectEventRecorded("C2S", true);
439 ExpectEventRecorded("C2F", true);
440
441 ExpectRlzPingSent(true);
442 }
443
444 TEST_F(RlzLibTest, OmniboxUsageSendsPingWhenDelayNegative) {
445 RLZTracker::InitRlzDelayed(true, -20, true, true);
446 SimulateOmniboxUsage();
447
448 // Omnibox events.
449 ExpectEventRecorded("C1I", true);
450 ExpectEventRecorded("C1S", true);
451 ExpectEventRecorded("C1F", true);
452
453 // Home page events.
454 ExpectEventRecorded("C2I", true);
455 ExpectEventRecorded("C2S", true);
456 ExpectEventRecorded("C2F", false);
457
458 ExpectRlzPingSent(true);
459 }
460
461 TEST_F(RlzLibTest, HomepageUsageDoesNotSendPingWhenDelayNegative) {
462 RLZTracker::InitRlzDelayed(true, -20, true, true);
463 SimulateHomepageUsage();
464
465 // Omnibox events.
466 ExpectEventRecorded("C1I", false);
467 ExpectEventRecorded("C1S", false);
468 ExpectEventRecorded("C1F", false);
469
470 // Home page events.
471 ExpectEventRecorded("C2I", false);
472 ExpectEventRecorded("C2S", false);
473 ExpectEventRecorded("C2F", true);
474
475 ExpectRlzPingSent(false);
476 }
477
478 TEST_F(RlzLibTest, GetAccessPointRlzOnIoThread) {
479 // Set dummy RLZ string.
480 rlz_lib::SetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, kOmniboxRlzString);
481
482 std::wstring rlz;
483
484 tracker_.set_assume_io_thread(true);
485 EXPECT_TRUE(RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz));
486 EXPECT_STREQ(kOmniboxRlzString, WideToUTF8(rlz).c_str());
487 }
488
489 TEST_F(RlzLibTest, GetAccessPointRlzNotOnIoThread) {
490 // Set dummy RLZ string.
491 rlz_lib::SetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, kOmniboxRlzString);
492
493 std::wstring rlz;
494
495 tracker_.set_assume_io_thread(false);
496 EXPECT_FALSE(RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz));
497 }
498
499 TEST_F(RlzLibTest, GetAccessPointRlzIsCached) {
500 // Set dummy RLZ string.
501 rlz_lib::SetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, kOmniboxRlzString);
502
503 std::wstring rlz;
504
505 tracker_.set_assume_io_thread(false);
506 EXPECT_FALSE(RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz));
507
508 tracker_.set_assume_io_thread(true);
509 EXPECT_TRUE(RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz));
510 EXPECT_STREQ(kOmniboxRlzString, WideToUTF8(rlz).c_str());
511
512 tracker_.set_assume_io_thread(false);
513 EXPECT_TRUE(RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz));
514 EXPECT_STREQ(kOmniboxRlzString, WideToUTF8(rlz).c_str());
515 }
516
517 TEST_F(RlzLibTest, PingInvalidatesRlzCache) {
518 // Set dummy RLZ string.
519 rlz_lib::SetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, kOmniboxRlzString);
520
521 std::wstring rlz;
522
523 // Prime the cache.
524 tracker_.set_assume_io_thread(true);
525 EXPECT_TRUE(RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz));
526 EXPECT_STREQ(kOmniboxRlzString, WideToUTF8(rlz).c_str());
527
528 // Make sure cache is valid.
529 tracker_.set_assume_io_thread(false);
530 EXPECT_TRUE(RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz));
531 EXPECT_STREQ(kOmniboxRlzString, WideToUTF8(rlz).c_str());
532
533 // Perform ping.
534 RLZTracker::InitRlzDelayed(true, 20, true, true);
535 InvokeDelayedInit();
536 ExpectRlzPingSent(true);
537
538 // Make sure cache is now invalid.
539 EXPECT_FALSE(RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz));
540 }
541
542 TEST_F(RlzLibTest, ObserveHandlesBadArgs) {
543 NavigationEntry entry(NULL, 0, GURL(), GURL(), string16(),
544 PageTransition::LINK);
545 tracker_.Observe(content::NOTIFICATION_NAV_ENTRY_PENDING,
546 NotificationService::AllSources(),
547 Details<NavigationEntry>(NULL));
548 tracker_.Observe(content::NOTIFICATION_NAV_ENTRY_PENDING,
549 NotificationService::AllSources(),
550 Details<NavigationEntry>(&entry));
551 }
OLDNEW
« chrome/browser/rlz/rlz.cc ('K') | « chrome/browser/rlz/rlz.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698