Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / safe_browsing / safe_browsing_test.cc
1 // Copyright (c) 2012 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 // This test uses the safebrowsing test server published at
6 // http://code.google.com/p/google-safe-browsing/ to test the safebrowsing
7 // protocol implemetation. Details of the safebrowsing testing flow is
8 // documented at
9 // http://code.google.com/p/google-safe-browsing/wiki/ProtocolTesting
10 //
11 // This test launches safebrowsing test server and issues several update
12 // requests against that server. Each update would get different data and after
13 // each update, the test will get a list of URLs from the test server to verify
14 // its repository. The test will succeed only if all updates are performed and
15 // URLs match what the server expected.
16
17 #include <vector>
18
19 #include "base/bind.h"
20 #include "base/command_line.h"
21 #include "base/environment.h"
22 #include "base/path_service.h"
23 #include "base/strings/string_number_conversions.h"
24 #include "base/strings/string_split.h"
25 #include "base/strings/stringprintf.h"
26 #include "base/strings/utf_string_conversions.h"
27 #include "base/synchronization/lock.h"
28 #include "base/test/test_timeouts.h"
29 #include "base/threading/platform_thread.h"
30 #include "base/threading/thread.h"
31 #include "base/time/time.h"
32 #include "chrome/browser/browser_process.h"
33 #include "chrome/browser/chrome_notification_types.h"
34 #include "chrome/browser/profiles/profile.h"
35 #include "chrome/browser/safe_browsing/database_manager.h"
36 #include "chrome/browser/safe_browsing/local_safebrowsing_test_server.h"
37 #include "chrome/browser/safe_browsing/protocol_manager.h"
38 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
39 #include "chrome/browser/ui/browser.h"
40 #include "chrome/common/chrome_switches.h"
41 #include "chrome/common/url_constants.h"
42 #include "chrome/test/base/in_process_browser_test.h"
43 #include "content/public/browser/browser_context.h"
44 #include "content/public/test/test_browser_thread.h"
45 #include "content/public/test/test_utils.h"
46 #include "net/base/load_flags.h"
47 #include "net/base/net_log.h"
48 #include "net/dns/host_resolver.h"
49 #include "net/test/python_utils.h"
50 #include "net/url_request/url_fetcher.h"
51 #include "net/url_request/url_fetcher_delegate.h"
52 #include "net/url_request/url_request_status.h"
53 #include "testing/gtest/include/gtest/gtest.h"
54
55 using content::BrowserThread;
56
57 namespace {
58
59 const base::FilePath::CharType kDataFile[] =
60     FILE_PATH_LITERAL("testing_input_nomac.dat");
61 const char kUrlVerifyPath[] = "safebrowsing/verify_urls";
62 const char kDBVerifyPath[] = "safebrowsing/verify_database";
63 const char kTestCompletePath[] = "test_complete";
64
65 struct PhishingUrl {
66   std::string url;
67   std::string list_name;
68   bool is_phishing;
69 };
70
71 // Parses server response for verify_urls. The expected format is:
72 //
73 // first.random.url.com/   internal-test-shavar   yes
74 // second.random.url.com/  internal-test-shavar   yes
75 // ...
76 bool ParsePhishingUrls(const std::string& data,
77                        std::vector<PhishingUrl>* phishing_urls) {
78   if (data.empty())
79     return false;
80
81   std::vector<std::string> urls;
82   base::SplitString(data, '\n', &urls);
83   for (size_t i = 0; i < urls.size(); ++i) {
84     if (urls[i].empty())
85       continue;
86     PhishingUrl phishing_url;
87     std::vector<std::string> record_parts;
88     base::SplitString(urls[i], '\t', &record_parts);
89     if (record_parts.size() != 3) {
90       LOG(ERROR) << "Unexpected URL format in phishing URL list: "
91                  << urls[i];
92       return false;
93     }
94     phishing_url.url = std::string(url::kHttpScheme) + "://" + record_parts[0];
95     phishing_url.list_name = record_parts[1];
96     if (record_parts[2] == "yes") {
97       phishing_url.is_phishing = true;
98     } else if (record_parts[2] == "no") {
99       phishing_url.is_phishing = false;
100     } else {
101       LOG(ERROR) << "Unrecognized expectation in " << urls[i]
102                  << ": " << record_parts[2];
103       return false;
104     }
105     phishing_urls->push_back(phishing_url);
106   }
107   return true;
108 }
109
110 class FakeSafeBrowsingService : public SafeBrowsingService {
111  public:
112   explicit FakeSafeBrowsingService(const std::string& url_prefix)
113       : url_prefix_(url_prefix) {}
114
115   SafeBrowsingProtocolConfig GetProtocolConfig() const override {
116     SafeBrowsingProtocolConfig config;
117     config.url_prefix = url_prefix_;
118     // Makes sure the auto update is not triggered. The tests will force the
119     // update when needed.
120     config.disable_auto_update = true;
121 #if defined(OS_ANDROID)
122     config.disable_connection_check = true;
123 #endif
124     config.client_name = "browser_tests";
125     return config;
126   }
127
128  private:
129   ~FakeSafeBrowsingService() override {}
130
131   std::string url_prefix_;
132
133   DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService);
134 };
135
136 // Factory that creates FakeSafeBrowsingService instances.
137 class TestSafeBrowsingServiceFactory : public SafeBrowsingServiceFactory {
138  public:
139   explicit TestSafeBrowsingServiceFactory(const std::string& url_prefix)
140       : url_prefix_(url_prefix) {}
141
142   SafeBrowsingService* CreateSafeBrowsingService() override {
143     return new FakeSafeBrowsingService(url_prefix_);
144   }
145
146  private:
147   std::string url_prefix_;
148 };
149
150 }  // namespace
151
152 // This starts the browser and keeps status of states related to SafeBrowsing.
153 class SafeBrowsingServerTest : public InProcessBrowserTest {
154  public:
155   SafeBrowsingServerTest()
156     : safe_browsing_service_(NULL),
157       is_database_ready_(true),
158       is_update_scheduled_(false),
159       is_checked_url_in_db_(false),
160       is_checked_url_safe_(false) {
161   }
162
163   ~SafeBrowsingServerTest() override {}
164
165   void UpdateSafeBrowsingStatus() {
166     ASSERT_TRUE(safe_browsing_service_);
167     base::AutoLock lock(update_status_mutex_);
168     last_update_ = safe_browsing_service_->protocol_manager_->last_update();
169     is_update_scheduled_ =
170         safe_browsing_service_->protocol_manager_->update_timer_.IsRunning();
171   }
172
173   void ForceUpdate() {
174     content::WindowedNotificationObserver observer(
175         chrome::NOTIFICATION_SAFE_BROWSING_UPDATE_COMPLETE,
176         content::Source<SafeBrowsingDatabaseManager>(database_manager()));
177     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
178         base::Bind(&SafeBrowsingServerTest::ForceUpdateOnIOThread,
179                    this));
180     observer.Wait();
181   }
182
183   void ForceUpdateOnIOThread() {
184     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
185     ASSERT_TRUE(safe_browsing_service_);
186     safe_browsing_service_->protocol_manager_->ForceScheduleNextUpdate(
187         base::TimeDelta::FromSeconds(0));
188   }
189
190   void CheckIsDatabaseReady() {
191     base::AutoLock lock(update_status_mutex_);
192     is_database_ready_ = !database_manager()->database_update_in_progress_;
193   }
194
195   void CheckUrl(SafeBrowsingDatabaseManager::Client* helper, const GURL& url) {
196     ASSERT_TRUE(safe_browsing_service_);
197     base::AutoLock lock(update_status_mutex_);
198     if (database_manager()->CheckBrowseUrl(url, helper)) {
199       is_checked_url_in_db_ = false;
200       is_checked_url_safe_ = true;
201     } else {
202       // In this case, Safebrowsing service will fetch the full hash
203       // from the server and examine that. Once it is done,
204       // set_is_checked_url_safe() will be called via callback.
205       is_checked_url_in_db_ = true;
206     }
207   }
208
209   SafeBrowsingDatabaseManager* database_manager() {
210     return safe_browsing_service_->database_manager().get();
211   }
212
213   bool is_checked_url_in_db() {
214     base::AutoLock l(update_status_mutex_);
215     return is_checked_url_in_db_;
216   }
217
218   void set_is_checked_url_safe(bool safe) {
219     base::AutoLock l(update_status_mutex_);
220     is_checked_url_safe_ = safe;
221   }
222
223   bool is_checked_url_safe() {
224     base::AutoLock l(update_status_mutex_);
225     return is_checked_url_safe_;
226   }
227
228   bool is_database_ready() {
229     base::AutoLock l(update_status_mutex_);
230     return is_database_ready_;
231   }
232
233   base::Time last_update() {
234     base::AutoLock l(update_status_mutex_);
235     return last_update_;
236   }
237
238   bool is_update_scheduled() {
239     base::AutoLock l(update_status_mutex_);
240     return is_update_scheduled_;
241   }
242
243   base::MessageLoop* SafeBrowsingMessageLoop() {
244     return database_manager()->safe_browsing_thread_->message_loop();
245   }
246
247   const net::SpawnedTestServer& test_server() const {
248     return *test_server_;
249   }
250
251  protected:
252   bool InitSafeBrowsingService() {
253     safe_browsing_service_ = g_browser_process->safe_browsing_service();
254     return safe_browsing_service_ != NULL;
255   }
256
257   void SetUp() override {
258     base::FilePath datafile_path;
259     ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &datafile_path));
260
261     datafile_path = datafile_path.Append(FILE_PATH_LITERAL("third_party"))
262           .Append(FILE_PATH_LITERAL("safe_browsing"))
263           .Append(FILE_PATH_LITERAL("testing"))
264           .Append(kDataFile);
265     test_server_.reset(new LocalSafeBrowsingTestServer(datafile_path));
266     ASSERT_TRUE(test_server_->Start());
267     LOG(INFO) << "server is " << test_server_->host_port_pair().ToString();
268
269     // Point to the testing server for all SafeBrowsing requests.
270     std::string url_prefix = test_server_->GetURL("safebrowsing").spec();
271     sb_factory_.reset(new TestSafeBrowsingServiceFactory(url_prefix));
272     SafeBrowsingService::RegisterFactory(sb_factory_.get());
273
274     InProcessBrowserTest::SetUp();
275   }
276
277   void TearDown() override {
278     InProcessBrowserTest::TearDown();
279
280     SafeBrowsingService::RegisterFactory(NULL);
281   }
282
283   void SetUpCommandLine(CommandLine* command_line) override {
284     // This test uses loopback. No need to use IPv6 especially it makes
285     // local requests slow on Windows trybot when ipv6 local address [::1]
286     // is not setup.
287     command_line->AppendSwitch(switches::kDisableIPv6);
288
289     // TODO(lzheng): The test server does not understand download related
290     // requests. We need to fix the server.
291     command_line->AppendSwitch(switches::kSbDisableDownloadProtection);
292
293     // TODO(gcasto): Generate new testing data that includes the
294     // client-side phishing whitelist.
295     command_line->AppendSwitch(
296         switches::kDisableClientSidePhishingDetection);
297
298     // TODO(kalman): Generate new testing data that includes the extension
299     // blacklist.
300     command_line->AppendSwitch(switches::kSbDisableExtensionBlacklist);
301
302     // TODO(tburkard): Generate new testing data that includes the side-effect
303     // free whitelist.
304     command_line->AppendSwitch(switches::kSbDisableSideEffectFreeWhitelist);
305   }
306
307   void SetTestStep(int step) {
308     std::string test_step = base::StringPrintf("test_step=%d", step);
309     safe_browsing_service_->protocol_manager_->set_additional_query(test_step);
310   }
311
312  private:
313   scoped_ptr<TestSafeBrowsingServiceFactory> sb_factory_;
314
315   SafeBrowsingService* safe_browsing_service_;
316
317   scoped_ptr<net::SpawnedTestServer> test_server_;
318
319   // Protects all variables below since they are read on UI thread
320   // but updated on IO thread or safebrowsing thread.
321   base::Lock update_status_mutex_;
322
323   // States associated with safebrowsing service updates.
324   bool is_database_ready_;
325   base::Time last_update_;
326   bool is_update_scheduled_;
327   // Indicates if there is a match between a URL's prefix and safebrowsing
328   // database (thus potentially it is a phishing URL).
329   bool is_checked_url_in_db_;
330   // True if last verified URL is not a phishing URL and thus it is safe.
331   bool is_checked_url_safe_;
332
333   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServerTest);
334 };
335
336 // A ref counted helper class that handles callbacks between IO thread and UI
337 // thread.
338 class SafeBrowsingServerTestHelper
339     : public base::RefCountedThreadSafe<SafeBrowsingServerTestHelper>,
340       public SafeBrowsingDatabaseManager::Client,
341       public net::URLFetcherDelegate {
342  public:
343   SafeBrowsingServerTestHelper(SafeBrowsingServerTest* safe_browsing_test,
344                                net::URLRequestContextGetter* request_context)
345       : safe_browsing_test_(safe_browsing_test),
346         response_status_(net::URLRequestStatus::FAILED),
347         request_context_(request_context) {
348   }
349
350   // Callbacks for SafeBrowsingDatabaseManager::Client.
351   void OnCheckBrowseUrlResult(const GURL& url,
352                               SBThreatType threat_type,
353                               const std::string& metadata) override {
354     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
355     EXPECT_TRUE(safe_browsing_test_->is_checked_url_in_db());
356     safe_browsing_test_->set_is_checked_url_safe(
357         threat_type == SB_THREAT_TYPE_SAFE);
358     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
359         base::Bind(&SafeBrowsingServerTestHelper::OnCheckUrlDone, this));
360   }
361
362   virtual void OnBlockingPageComplete(bool proceed) {
363     NOTREACHED() << "Not implemented.";
364   }
365
366   // Functions and callbacks related to CheckUrl. These are used to verify
367   // phishing URLs.
368   void CheckUrl(const GURL& url) {
369     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
370         base::Bind(&SafeBrowsingServerTestHelper::CheckUrlOnIOThread,
371                    this, url));
372     content::RunMessageLoop();
373   }
374   void CheckUrlOnIOThread(const GURL& url) {
375     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
376     safe_browsing_test_->CheckUrl(this, url);
377     if (!safe_browsing_test_->is_checked_url_in_db()) {
378       // Ends the checking since this URL's prefix is not in database.
379       BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
380         base::Bind(&SafeBrowsingServerTestHelper::OnCheckUrlDone, this));
381     }
382     // Otherwise, OnCheckUrlDone is called in OnUrlCheckResult since
383     // safebrowsing service further fetches hashes from safebrowsing server.
384   }
385
386   void OnCheckUrlDone() {
387     StopUILoop();
388   }
389
390   // Updates status from IO Thread.
391   void CheckStatusOnIOThread() {
392     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
393     safe_browsing_test_->UpdateSafeBrowsingStatus();
394     safe_browsing_test_->SafeBrowsingMessageLoop()->PostTask(FROM_HERE,
395         base::Bind(&SafeBrowsingServerTestHelper::CheckIsDatabaseReady, this));
396   }
397
398   // Checks status in SafeBrowsing Thread.
399   void CheckIsDatabaseReady() {
400     EXPECT_EQ(base::MessageLoop::current(),
401               safe_browsing_test_->SafeBrowsingMessageLoop());
402     safe_browsing_test_->CheckIsDatabaseReady();
403     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
404         base::Bind(&SafeBrowsingServerTestHelper::OnWaitForStatusUpdateDone,
405                    this));
406   }
407
408   void OnWaitForStatusUpdateDone() {
409     StopUILoop();
410   }
411
412   // Update safebrowsing status.
413   void UpdateStatus() {
414     BrowserThread::PostTask(
415         BrowserThread::IO,
416         FROM_HERE,
417         base::Bind(&SafeBrowsingServerTestHelper::CheckStatusOnIOThread, this));
418     // Will continue after OnWaitForStatusUpdateDone().
419     content::RunMessageLoop();
420   }
421
422   // Calls test server to fetch database for verification.
423   net::URLRequestStatus::Status FetchDBToVerify(
424       const net::SpawnedTestServer& test_server,
425       int test_step) {
426     // TODO(lzheng): Remove chunk_type=add once it is not needed by the server.
427     std::string path = base::StringPrintf(
428         "%s?client=chromium&appver=1.0&pver=3.0&test_step=%d&chunk_type=add",
429         kDBVerifyPath, test_step);
430     return FetchUrl(test_server.GetURL(path));
431   }
432
433   // Calls test server to fetch URLs for verification.
434   net::URLRequestStatus::Status FetchUrlsToVerify(
435       const net::SpawnedTestServer& test_server,
436       int test_step) {
437     std::string path = base::StringPrintf(
438         "%s?client=chromium&appver=1.0&pver=3.0&test_step=%d",
439         kUrlVerifyPath, test_step);
440     return FetchUrl(test_server.GetURL(path));
441   }
442
443   // Calls test server to check if test data is done. E.g.: if there is a
444   // bad URL that server expects test to fetch full hash but the test didn't,
445   // this verification will fail.
446   net::URLRequestStatus::Status VerifyTestComplete(
447       const net::SpawnedTestServer& test_server,
448       int test_step) {
449     std::string path = base::StringPrintf(
450         "%s?test_step=%d", kTestCompletePath, test_step);
451     return FetchUrl(test_server.GetURL(path));
452   }
453
454   // Callback for URLFetcher.
455   void OnURLFetchComplete(const net::URLFetcher* source) override {
456     source->GetResponseAsString(&response_data_);
457     response_status_ = source->GetStatus().status();
458     StopUILoop();
459   }
460
461   const std::string& response_data() {
462     return response_data_;
463   }
464
465  private:
466   friend class base::RefCountedThreadSafe<SafeBrowsingServerTestHelper>;
467   ~SafeBrowsingServerTestHelper() override {}
468
469   // Stops UI loop after desired status is updated.
470   void StopUILoop() {
471     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
472     base::MessageLoopForUI::current()->Quit();
473   }
474
475   // Fetch a URL. If message_loop_started is true, starts the message loop
476   // so the caller could wait till OnURLFetchComplete is called.
477   net::URLRequestStatus::Status FetchUrl(const GURL& url) {
478     url_fetcher_.reset(net::URLFetcher::Create(
479         url, net::URLFetcher::GET, this));
480     url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
481     url_fetcher_->SetRequestContext(request_context_);
482     url_fetcher_->Start();
483     content::RunMessageLoop();
484     return response_status_;
485   }
486
487   base::OneShotTimer<SafeBrowsingServerTestHelper> check_update_timer_;
488   SafeBrowsingServerTest* safe_browsing_test_;
489   scoped_ptr<net::URLFetcher> url_fetcher_;
490   std::string response_data_;
491   net::URLRequestStatus::Status response_status_;
492   net::URLRequestContextGetter* request_context_;
493   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServerTestHelper);
494 };
495
496 // TODO(shess): Disabled pending new data for third_party/safe_browsing/testing/
497 IN_PROC_BROWSER_TEST_F(SafeBrowsingServerTest,
498                        DISABLED_SafeBrowsingServerTest) {
499   LOG(INFO) << "Start test";
500   ASSERT_TRUE(InitSafeBrowsingService());
501
502   net::URLRequestContextGetter* request_context =
503       browser()->profile()->GetRequestContext();
504   scoped_refptr<SafeBrowsingServerTestHelper> safe_browsing_helper(
505       new SafeBrowsingServerTestHelper(this, request_context));
506   int last_step = 0;
507
508   // Waits and makes sure safebrowsing update is not happening.
509   // The wait will stop once OnWaitForStatusUpdateDone in
510   // safe_browsing_helper is called and status from safe_browsing_service_
511   // is checked.
512   safe_browsing_helper->UpdateStatus();
513   EXPECT_TRUE(is_database_ready());
514   EXPECT_FALSE(is_update_scheduled());
515   EXPECT_TRUE(last_update().is_null());
516   // Starts updates. After each update, the test will fetch a list of URLs with
517   // expected results to verify with safebrowsing service. If there is no error,
518   // the test moves on to the next step to get more update chunks.
519   // This repeats till there is no update data.
520   for (int step = 1;; step++) {
521     // Every step should be a fresh start.
522     SCOPED_TRACE(base::StringPrintf("step=%d", step));
523     EXPECT_TRUE(is_database_ready());
524     EXPECT_FALSE(is_update_scheduled());
525
526     // Starts safebrowsing update on IO thread. Waits till scheduled
527     // update finishes.
528     base::Time now = base::Time::Now();
529     SetTestStep(step);
530     ForceUpdate();
531
532     safe_browsing_helper->UpdateStatus();
533     EXPECT_TRUE(is_database_ready());
534     EXPECT_FALSE(is_update_scheduled());
535     EXPECT_FALSE(last_update().is_null());
536     if (last_update() < now) {
537       // This means no data available anymore.
538       break;
539     }
540
541     // Fetches URLs to verify and waits till server responses with data.
542     EXPECT_EQ(net::URLRequestStatus::SUCCESS,
543               safe_browsing_helper->FetchUrlsToVerify(test_server(), step));
544
545     std::vector<PhishingUrl> phishing_urls;
546     EXPECT_TRUE(ParsePhishingUrls(safe_browsing_helper->response_data(),
547                                   &phishing_urls));
548     EXPECT_GT(phishing_urls.size(), 0U);
549     for (size_t j = 0; j < phishing_urls.size(); ++j) {
550       // Verifes with server if a URL is a phishing URL and waits till server
551       // responses.
552       safe_browsing_helper->CheckUrl(GURL(phishing_urls[j].url));
553       if (phishing_urls[j].is_phishing) {
554         EXPECT_TRUE(is_checked_url_in_db())
555             << phishing_urls[j].url
556             << " is_phishing: " << phishing_urls[j].is_phishing
557             << " test step: " << step;
558         EXPECT_FALSE(is_checked_url_safe())
559             << phishing_urls[j].url
560             << " is_phishing: " << phishing_urls[j].is_phishing
561             << " test step: " << step;
562       } else {
563         EXPECT_TRUE(is_checked_url_safe())
564             << phishing_urls[j].url
565             << " is_phishing: " << phishing_urls[j].is_phishing
566             << " test step: " << step;
567       }
568     }
569     // TODO(lzheng): We should verify the fetched database with local
570     // database to make sure they match.
571     EXPECT_EQ(net::URLRequestStatus::SUCCESS,
572               safe_browsing_helper->FetchDBToVerify(test_server(), step));
573     EXPECT_GT(safe_browsing_helper->response_data().size(), 0U);
574     last_step = step;
575   }
576
577   // Verifies with server if test is done and waits till server responses.
578   EXPECT_EQ(net::URLRequestStatus::SUCCESS,
579             safe_browsing_helper->VerifyTestComplete(test_server(), last_step));
580   EXPECT_EQ("yes", safe_browsing_helper->response_data());
581 }