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#include "chrome/test/base/testing_profile.h"
6
7#include "build/build_config.h"
8
9#include "base/base_paths.h"
10#include "base/command_line.h"
11#include "base/file_util.h"
12#include "base/message_loop/message_loop_proxy.h"
13#include "base/path_service.h"
14#include "base/prefs/testing_pref_store.h"
15#include "base/run_loop.h"
16#include "base/strings/string_number_conversions.h"
17#include "chrome/browser/autocomplete/autocomplete_classifier.h"
18#include "chrome/browser/bookmarks/bookmark_model.h"
19#include "chrome/browser/bookmarks/bookmark_model_factory.h"
20#include "chrome/browser/browser_process.h"
21#include "chrome/browser/chrome_notification_types.h"
22#include "chrome/browser/content_settings/host_content_settings_map.h"
23#include "chrome/browser/extensions/extension_service.h"
24#include "chrome/browser/extensions/extension_special_storage_policy.h"
25#include "chrome/browser/extensions/extension_system.h"
26#include "chrome/browser/extensions/extension_system_factory.h"
27#include "chrome/browser/extensions/test_extension_system.h"
28#include "chrome/browser/favicon/favicon_service.h"
29#include "chrome/browser/favicon/favicon_service_factory.h"
30#include "chrome/browser/geolocation/chrome_geolocation_permission_context.h"
31#include "chrome/browser/geolocation/chrome_geolocation_permission_context_factory.h"
32#include "chrome/browser/history/history_backend.h"
33#include "chrome/browser/history/history_db_task.h"
34#include "chrome/browser/history/history_service.h"
35#include "chrome/browser/history/history_service_factory.h"
36#include "chrome/browser/history/shortcuts_backend.h"
37#include "chrome/browser/history/shortcuts_backend_factory.h"
38#include "chrome/browser/history/top_sites.h"
39#include "chrome/browser/history/web_history_service_factory.h"
40#include "chrome/browser/net/pref_proxy_config_tracker.h"
41#include "chrome/browser/net/proxy_service_factory.h"
42#include "chrome/browser/notifications/desktop_notification_service.h"
43#include "chrome/browser/notifications/desktop_notification_service_factory.h"
44#include "chrome/browser/policy/profile_policy_connector.h"
45#include "chrome/browser/policy/profile_policy_connector_factory.h"
46#include "chrome/browser/prefs/browser_prefs.h"
47#include "chrome/browser/prefs/pref_service_syncable.h"
48#include "chrome/browser/prerender/prerender_manager.h"
49#include "chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.h"
50#include "chrome/browser/profiles/storage_partition_descriptor.h"
51#include "chrome/browser/search_engines/template_url_fetcher_factory.h"
52#include "chrome/browser/webdata/web_data_service.h"
53#include "chrome/browser/webdata/web_data_service_factory.h"
54#include "chrome/common/chrome_constants.h"
55#include "chrome/common/chrome_switches.h"
56#include "chrome/common/pref_names.h"
57#include "chrome/common/url_constants.h"
58#include "chrome/test/base/bookmark_load_observer.h"
59#include "chrome/test/base/history_index_restore_observer.h"
60#include "chrome/test/base/testing_pref_service_syncable.h"
61#include "chrome/test/base/ui_test_utils.h"
62#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
63#include "components/user_prefs/user_prefs.h"
64#include "content/public/browser/browser_thread.h"
65#include "content/public/browser/notification_service.h"
66#include "content/public/browser/render_process_host.h"
67#include "content/public/browser/storage_partition.h"
68#include "content/public/test/mock_resource_context.h"
69#include "content/public/test/test_utils.h"
70#include "extensions/common/constants.h"
71#include "net/cookies/cookie_monster.h"
72#include "net/url_request/url_request_context.h"
73#include "net/url_request/url_request_context_getter.h"
74#include "net/url_request/url_request_test_util.h"
75#include "testing/gmock/include/gmock/gmock.h"
76
77#if defined(ENABLE_CONFIGURATION_POLICY)
78#include "chrome/browser/policy/configuration_policy_provider.h"
79#include "chrome/browser/policy/policy_service_impl.h"
80#else
81#include "chrome/browser/policy/policy_service_stub.h"
82#endif  // defined(ENABLE_CONFIGURATION_POLICY)
83
84using base::Time;
85using content::BrowserThread;
86using content::DownloadManagerDelegate;
87using testing::NiceMock;
88using testing::Return;
89
90namespace {
91
92// Task used to make sure history has finished processing a request. Intended
93// for use with BlockUntilHistoryProcessesPendingRequests.
94
95class QuittingHistoryDBTask : public history::HistoryDBTask {
96 public:
97  QuittingHistoryDBTask() {}
98
99  virtual bool RunOnDBThread(history::HistoryBackend* backend,
100                             history::HistoryDatabase* db) OVERRIDE {
101    return true;
102  }
103
104  virtual void DoneRunOnMainThread() OVERRIDE {
105    base::MessageLoop::current()->Quit();
106  }
107
108 private:
109  virtual ~QuittingHistoryDBTask() {}
110
111  DISALLOW_COPY_AND_ASSIGN(QuittingHistoryDBTask);
112};
113
114class TestExtensionURLRequestContext : public net::URLRequestContext {
115 public:
116  TestExtensionURLRequestContext() {
117    net::CookieMonster* cookie_monster = new net::CookieMonster(NULL, NULL);
118    const char* schemes[] = {extensions::kExtensionScheme};
119    cookie_monster->SetCookieableSchemes(schemes, 1);
120    set_cookie_store(cookie_monster);
121  }
122
123  virtual ~TestExtensionURLRequestContext() {}
124};
125
126class TestExtensionURLRequestContextGetter
127    : public net::URLRequestContextGetter {
128 public:
129  virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE {
130    if (!context_.get())
131      context_.reset(new TestExtensionURLRequestContext());
132    return context_.get();
133  }
134  virtual scoped_refptr<base::SingleThreadTaskRunner>
135      GetNetworkTaskRunner() const OVERRIDE {
136    return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
137  }
138
139 protected:
140  virtual ~TestExtensionURLRequestContextGetter() {}
141
142 private:
143  scoped_ptr<net::URLRequestContext> context_;
144};
145
146BrowserContextKeyedService* CreateTestDesktopNotificationService(
147    content::BrowserContext* profile) {
148#if defined(ENABLE_NOTIFICATIONS)
149  return new DesktopNotificationService(static_cast<Profile*>(profile), NULL);
150#else
151  return NULL;
152#endif
153}
154
155}  // namespace
156
157// static
158#if defined(OS_CHROMEOS)
159// Must be kept in sync with
160// ChromeBrowserMainPartsChromeos::PreEarlyInitialization.
161const char TestingProfile::kTestUserProfileDir[] = "test-user";
162#else
163const char TestingProfile::kTestUserProfileDir[] = "Default";
164#endif
165
166TestingProfile::TestingProfile()
167    : start_time_(Time::Now()),
168      testing_prefs_(NULL),
169      incognito_(false),
170      original_profile_(NULL),
171      last_session_exited_cleanly_(true),
172      browser_context_dependency_manager_(
173          BrowserContextDependencyManager::GetInstance()),
174      resource_context_(NULL),
175      delegate_(NULL) {
176  CreateTempProfileDir();
177  profile_path_ = temp_dir_.path();
178
179  Init();
180  FinishInit();
181}
182
183TestingProfile::TestingProfile(const base::FilePath& path)
184    : start_time_(Time::Now()),
185      testing_prefs_(NULL),
186      incognito_(false),
187      original_profile_(NULL),
188      last_session_exited_cleanly_(true),
189      profile_path_(path),
190      browser_context_dependency_manager_(
191          BrowserContextDependencyManager::GetInstance()),
192      resource_context_(NULL),
193      delegate_(NULL) {
194  Init();
195  FinishInit();
196}
197
198TestingProfile::TestingProfile(const base::FilePath& path,
199                               Delegate* delegate)
200    : start_time_(Time::Now()),
201      testing_prefs_(NULL),
202      incognito_(false),
203      original_profile_(NULL),
204      last_session_exited_cleanly_(true),
205      profile_path_(path),
206      browser_context_dependency_manager_(
207          BrowserContextDependencyManager::GetInstance()),
208      resource_context_(NULL),
209      delegate_(delegate) {
210  Init();
211  if (delegate_) {
212    base::MessageLoop::current()->PostTask(
213        FROM_HERE,
214        base::Bind(&TestingProfile::FinishInit, base::Unretained(this)));
215  } else {
216    FinishInit();
217  }
218}
219
220TestingProfile::TestingProfile(
221    const base::FilePath& path,
222    Delegate* delegate,
223    scoped_refptr<ExtensionSpecialStoragePolicy> extension_policy,
224    scoped_ptr<PrefServiceSyncable> prefs)
225    : start_time_(Time::Now()),
226      prefs_(prefs.release()),
227      testing_prefs_(NULL),
228      incognito_(false),
229      original_profile_(NULL),
230      last_session_exited_cleanly_(true),
231      extension_special_storage_policy_(extension_policy),
232      profile_path_(path),
233      browser_context_dependency_manager_(
234          BrowserContextDependencyManager::GetInstance()),
235      resource_context_(NULL),
236      delegate_(delegate) {
237
238  // If no profile path was supplied, create one.
239  if (profile_path_.empty()) {
240    CreateTempProfileDir();
241    profile_path_ = temp_dir_.path();
242  }
243
244  Init();
245  // If caller supplied a delegate, delay the FinishInit invocation until other
246  // tasks have run.
247  // TODO(atwilson): See if this is still required once we convert the current
248  // users of the constructor that takes a Delegate* param.
249  if (delegate_) {
250    base::MessageLoop::current()->PostTask(
251        FROM_HERE,
252        base::Bind(&TestingProfile::FinishInit, base::Unretained(this)));
253  } else {
254    FinishInit();
255  }
256}
257
258void TestingProfile::CreateTempProfileDir() {
259  if (!temp_dir_.CreateUniqueTempDir()) {
260    LOG(ERROR) << "Failed to create unique temporary directory.";
261
262    // Fallback logic in case we fail to create unique temporary directory.
263    base::FilePath system_tmp_dir;
264    bool success = PathService::Get(base::DIR_TEMP, &system_tmp_dir);
265
266    // We're severly screwed if we can't get the system temporary
267    // directory. Die now to avoid writing to the filesystem root
268    // or other bad places.
269    CHECK(success);
270
271    base::FilePath fallback_dir(
272        system_tmp_dir.AppendASCII("TestingProfilePath"));
273    base::DeleteFile(fallback_dir, true);
274    file_util::CreateDirectory(fallback_dir);
275    if (!temp_dir_.Set(fallback_dir)) {
276      // That shouldn't happen, but if it does, try to recover.
277      LOG(ERROR) << "Failed to use a fallback temporary directory.";
278
279      // We're screwed if this fails, see CHECK above.
280      CHECK(temp_dir_.Set(system_tmp_dir));
281    }
282  }
283}
284
285void TestingProfile::Init() {
286  // If threads have been initialized, we should be on the UI thread.
287  DCHECK(!content::BrowserThread::IsThreadInitialized(
288             content::BrowserThread::UI) ||
289         content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
290
291  // Normally this would happen during browser startup, but for tests
292  // we need to trigger creation of Profile-related services.
293  ChromeBrowserMainExtraPartsProfiles::
294      EnsureBrowserContextKeyedServiceFactoriesBuilt();
295
296  if (prefs_.get())
297    user_prefs::UserPrefs::Set(this, prefs_.get());
298  else
299    CreateTestingPrefService();
300
301  if (!base::PathExists(profile_path_))
302    file_util::CreateDirectory(profile_path_);
303
304  // TODO(joaodasilva): remove this once this PKS isn't created in ProfileImpl
305  // anymore, after converting the PrefService to a PKS. Until then it must
306  // be associated with a TestingProfile too.
307  CreateProfilePolicyConnector();
308
309  extensions::ExtensionSystemFactory::GetInstance()->SetTestingFactory(
310      this, extensions::TestExtensionSystem::Build);
311
312  browser_context_dependency_manager_->CreateBrowserContextServices(this, true);
313
314#if defined(ENABLE_NOTIFICATIONS)
315  // Install profile keyed service factory hooks for dummy/test services
316  DesktopNotificationServiceFactory::GetInstance()->SetTestingFactory(
317      this, CreateTestDesktopNotificationService);
318#endif
319}
320
321void TestingProfile::FinishInit() {
322  DCHECK(content::NotificationService::current());
323  content::NotificationService::current()->Notify(
324      chrome::NOTIFICATION_PROFILE_CREATED,
325      content::Source<Profile>(static_cast<Profile*>(this)),
326      content::NotificationService::NoDetails());
327
328  if (delegate_)
329    delegate_->OnProfileCreated(this, true, false);
330}
331
332TestingProfile::~TestingProfile() {
333  // Any objects holding live URLFetchers should be deleted before teardown.
334  TemplateURLFetcherFactory::ShutdownForProfile(this);
335
336  MaybeSendDestroyedNotification();
337
338  browser_context_dependency_manager_->DestroyBrowserContextServices(this);
339
340  if (host_content_settings_map_.get())
341    host_content_settings_map_->ShutdownOnUIThread();
342
343  DestroyTopSites();
344
345  if (pref_proxy_config_tracker_.get())
346    pref_proxy_config_tracker_->DetachFromPrefService();
347  // Failing a post == leaks == heapcheck failure. Make that an immediate test
348  // failure.
349  if (resource_context_) {
350    CHECK(BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE,
351                                    resource_context_));
352    resource_context_ = NULL;
353    content::RunAllPendingInMessageLoop(BrowserThread::IO);
354  }
355}
356
357static BrowserContextKeyedService* BuildFaviconService(
358    content::BrowserContext* profile) {
359  return new FaviconService(
360      HistoryServiceFactory::GetForProfileWithoutCreating(
361          static_cast<Profile*>(profile)));
362}
363
364void TestingProfile::CreateFaviconService() {
365  // It is up to the caller to create the history service if one is needed.
366  FaviconServiceFactory::GetInstance()->SetTestingFactory(
367      this, BuildFaviconService);
368}
369
370static BrowserContextKeyedService* BuildHistoryService(
371    content::BrowserContext* profile) {
372  return new HistoryService(static_cast<Profile*>(profile));
373}
374
375bool TestingProfile::CreateHistoryService(bool delete_file, bool no_db) {
376  DestroyHistoryService();
377  if (delete_file) {
378    base::FilePath path = GetPath();
379    path = path.Append(chrome::kHistoryFilename);
380    if (!base::DeleteFile(path, false) || base::PathExists(path))
381      return false;
382  }
383  // This will create and init the history service.
384  HistoryService* history_service = static_cast<HistoryService*>(
385      HistoryServiceFactory::GetInstance()->SetTestingFactoryAndUse(
386          this, BuildHistoryService));
387  if (!history_service->Init(this->GetPath(),
388                             BookmarkModelFactory::GetForProfile(this),
389                             no_db)) {
390    HistoryServiceFactory::GetInstance()->SetTestingFactoryAndUse(this, NULL);
391  }
392  // Disable WebHistoryService by default, since it makes network requests.
393  WebHistoryServiceFactory::GetInstance()->SetTestingFactory(this, NULL);
394  return true;
395}
396
397void TestingProfile::DestroyHistoryService() {
398  HistoryService* history_service =
399      HistoryServiceFactory::GetForProfileWithoutCreating(this);
400  if (!history_service)
401    return;
402
403  history_service->NotifyRenderProcessHostDestruction(0);
404  history_service->SetOnBackendDestroyTask(base::MessageLoop::QuitClosure());
405  history_service->Cleanup();
406  HistoryServiceFactory::ShutdownForProfile(this);
407
408  // Wait for the backend class to terminate before deleting the files and
409  // moving to the next test. Note: if this never terminates, somebody is
410  // probably leaking a reference to the history backend, so it never calls
411  // our destroy task.
412  base::MessageLoop::current()->Run();
413
414  // Make sure we don't have any event pending that could disrupt the next
415  // test.
416  base::MessageLoop::current()->PostTask(FROM_HERE,
417                                         base::MessageLoop::QuitClosure());
418  base::MessageLoop::current()->Run();
419}
420
421void TestingProfile::CreateTopSites() {
422  DestroyTopSites();
423  top_sites_ = history::TopSites::Create(
424      this, GetPath().Append(chrome::kTopSitesFilename));
425}
426
427void TestingProfile::DestroyTopSites() {
428  if (top_sites_.get()) {
429    top_sites_->Shutdown();
430    top_sites_ = NULL;
431    // TopSitesImpl::Shutdown schedules some tasks (from TopSitesBackend) that
432    // need to be run to properly shutdown. Run all pending tasks now. This is
433    // normally handled by browser_process shutdown.
434    if (base::MessageLoop::current())
435      base::MessageLoop::current()->RunUntilIdle();
436  }
437}
438
439static BrowserContextKeyedService* BuildBookmarkModel(
440    content::BrowserContext* context) {
441  Profile* profile = static_cast<Profile*>(context);
442  BookmarkModel* bookmark_model = new BookmarkModel(profile);
443  bookmark_model->Load(profile->GetIOTaskRunner());
444  return bookmark_model;
445}
446
447
448void TestingProfile::CreateBookmarkModel(bool delete_file) {
449  if (delete_file) {
450    base::FilePath path = GetPath().Append(chrome::kBookmarksFileName);
451    base::DeleteFile(path, false);
452  }
453  // This will create a bookmark model.
454  BookmarkModel* bookmark_service = static_cast<BookmarkModel*>(
455      BookmarkModelFactory::GetInstance()->SetTestingFactoryAndUse(
456          this, BuildBookmarkModel));
457
458  HistoryService* history_service =
459      HistoryServiceFactory::GetForProfileWithoutCreating(this);
460  if (history_service) {
461    history_service->history_backend_->bookmark_service_ = bookmark_service;
462    history_service->history_backend_->expirer_.bookmark_service_ =
463        bookmark_service;
464  }
465}
466
467static BrowserContextKeyedService* BuildWebDataService(
468    content::BrowserContext* profile) {
469  return new WebDataServiceWrapper(static_cast<Profile*>(profile));
470}
471
472void TestingProfile::CreateWebDataService() {
473  WebDataServiceFactory::GetInstance()->SetTestingFactory(
474      this, BuildWebDataService);
475}
476
477void TestingProfile::BlockUntilHistoryIndexIsRefreshed() {
478  // Only get the history service if it actually exists since the caller of the
479  // test should explicitly call CreateHistoryService to build it.
480  HistoryService* history_service =
481      HistoryServiceFactory::GetForProfileWithoutCreating(this);
482  DCHECK(history_service);
483  history::InMemoryURLIndex* index = history_service->InMemoryIndex();
484  if (!index || index->restored())
485    return;
486  base::RunLoop run_loop;
487  HistoryIndexRestoreObserver observer(
488      content::GetQuitTaskForRunLoop(&run_loop));
489  index->set_restore_cache_observer(&observer);
490  run_loop.Run();
491  index->set_restore_cache_observer(NULL);
492  DCHECK(index->restored());
493}
494
495// TODO(phajdan.jr): Doesn't this hang if Top Sites are already loaded?
496void TestingProfile::BlockUntilTopSitesLoaded() {
497  content::WindowedNotificationObserver top_sites_loaded_observer(
498      chrome::NOTIFICATION_TOP_SITES_LOADED,
499      content::NotificationService::AllSources());
500  if (!HistoryServiceFactory::GetForProfile(this, Profile::EXPLICIT_ACCESS))
501    GetTopSites()->HistoryLoaded();
502  top_sites_loaded_observer.Wait();
503}
504
505base::FilePath TestingProfile::GetPath() const {
506  return profile_path_;
507}
508
509scoped_refptr<base::SequencedTaskRunner> TestingProfile::GetIOTaskRunner() {
510  return base::MessageLoop::current()->message_loop_proxy();
511}
512
513TestingPrefServiceSyncable* TestingProfile::GetTestingPrefService() {
514  if (!prefs_.get())
515    CreateTestingPrefService();
516  DCHECK(testing_prefs_);
517  return testing_prefs_;
518}
519
520TestingProfile* TestingProfile::AsTestingProfile() {
521  return this;
522}
523
524std::string TestingProfile::GetProfileName() {
525  return std::string("testing_profile");
526}
527
528bool TestingProfile::IsOffTheRecord() const {
529  return incognito_;
530}
531
532void TestingProfile::SetOffTheRecordProfile(Profile* profile) {
533  incognito_profile_.reset(profile);
534}
535
536void TestingProfile::SetOriginalProfile(Profile* profile) {
537  original_profile_ = profile;
538}
539
540Profile* TestingProfile::GetOffTheRecordProfile() {
541  return incognito_profile_.get();
542}
543
544bool TestingProfile::HasOffTheRecordProfile() {
545  return incognito_profile_.get() != NULL;
546}
547
548Profile* TestingProfile::GetOriginalProfile() {
549  if (original_profile_)
550    return original_profile_;
551  return this;
552}
553
554bool TestingProfile::IsManaged() {
555  return GetPrefs()->GetBoolean(prefs::kProfileIsManaged) ||
556      !GetPrefs()->GetString(prefs::kManagedUserId).empty();
557}
558
559ExtensionService* TestingProfile::GetExtensionService() {
560  return extensions::ExtensionSystem::Get(this)->extension_service();
561}
562
563void TestingProfile::SetExtensionSpecialStoragePolicy(
564    ExtensionSpecialStoragePolicy* extension_special_storage_policy) {
565  extension_special_storage_policy_ = extension_special_storage_policy;
566}
567
568ExtensionSpecialStoragePolicy*
569TestingProfile::GetExtensionSpecialStoragePolicy() {
570  if (!extension_special_storage_policy_.get())
571    extension_special_storage_policy_ = new ExtensionSpecialStoragePolicy(NULL);
572  return extension_special_storage_policy_.get();
573}
574
575net::CookieMonster* TestingProfile::GetCookieMonster() {
576  if (!GetRequestContext())
577    return NULL;
578  return GetRequestContext()->GetURLRequestContext()->cookie_store()->
579      GetCookieMonster();
580}
581
582void TestingProfile::CreateTestingPrefService() {
583  DCHECK(!prefs_.get());
584  testing_prefs_ = new TestingPrefServiceSyncable();
585  prefs_.reset(testing_prefs_);
586  user_prefs::UserPrefs::Set(this, prefs_.get());
587  chrome::RegisterUserProfilePrefs(testing_prefs_->registry());
588}
589
590void TestingProfile::CreateProfilePolicyConnector() {
591  scoped_ptr<policy::PolicyService> service;
592#if defined(ENABLE_CONFIGURATION_POLICY)
593  std::vector<policy::ConfigurationPolicyProvider*> providers;
594  service.reset(new policy::PolicyServiceImpl(providers));
595#else
596  service.reset(new policy::PolicyServiceStub());
597#endif
598  profile_policy_connector_.reset(
599      new policy::ProfilePolicyConnector(this));
600  profile_policy_connector_->InitForTesting(service.Pass());
601  policy::ProfilePolicyConnectorFactory::GetInstance()->SetServiceForTesting(
602      this, profile_policy_connector_.get());
603  CHECK_EQ(profile_policy_connector_.get(),
604           policy::ProfilePolicyConnectorFactory::GetForProfile(this));
605}
606
607PrefService* TestingProfile::GetPrefs() {
608  if (!prefs_.get()) {
609    CreateTestingPrefService();
610  }
611  return prefs_.get();
612}
613
614history::TopSites* TestingProfile::GetTopSites() {
615  return top_sites_.get();
616}
617
618history::TopSites* TestingProfile::GetTopSitesWithoutCreating() {
619  return top_sites_.get();
620}
621
622DownloadManagerDelegate* TestingProfile::GetDownloadManagerDelegate() {
623  return NULL;
624}
625
626net::URLRequestContextGetter* TestingProfile::GetRequestContext() {
627  return GetDefaultStoragePartition(this)->GetURLRequestContext();
628}
629
630net::URLRequestContextGetter* TestingProfile::CreateRequestContext(
631    content::ProtocolHandlerMap* protocol_handlers) {
632  return new net::TestURLRequestContextGetter(
633            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
634}
635
636net::URLRequestContextGetter* TestingProfile::GetRequestContextForRenderProcess(
637    int renderer_child_id) {
638  content::RenderProcessHost* rph = content::RenderProcessHost::FromID(
639      renderer_child_id);
640  return rph->GetStoragePartition()->GetURLRequestContext();
641}
642
643net::URLRequestContextGetter* TestingProfile::GetMediaRequestContext() {
644  return NULL;
645}
646
647net::URLRequestContextGetter*
648TestingProfile::GetMediaRequestContextForRenderProcess(
649    int renderer_child_id) {
650  return NULL;
651}
652
653net::URLRequestContextGetter*
654TestingProfile::GetMediaRequestContextForStoragePartition(
655    const base::FilePath& partition_path,
656    bool in_memory) {
657  return NULL;
658}
659
660void TestingProfile::RequestMIDISysExPermission(
661      int render_process_id,
662      int render_view_id,
663      const GURL& requesting_frame,
664      const MIDISysExPermissionCallback& callback) {
665  // Always reject requests for testing.
666  callback.Run(false);
667}
668
669net::URLRequestContextGetter* TestingProfile::GetRequestContextForExtensions() {
670  if (!extensions_request_context_.get())
671    extensions_request_context_ = new TestExtensionURLRequestContextGetter();
672  return extensions_request_context_.get();
673}
674
675net::SSLConfigService* TestingProfile::GetSSLConfigService() {
676  if (!GetRequestContext())
677    return NULL;
678  return GetRequestContext()->GetURLRequestContext()->ssl_config_service();
679}
680
681net::URLRequestContextGetter*
682TestingProfile::CreateRequestContextForStoragePartition(
683    const base::FilePath& partition_path,
684    bool in_memory,
685    content::ProtocolHandlerMap* protocol_handlers) {
686  // We don't test storage partitions here yet, so returning the same dummy
687  // context is sufficient for now.
688  return GetRequestContext();
689}
690
691content::ResourceContext* TestingProfile::GetResourceContext() {
692  if (!resource_context_)
693    resource_context_ = new content::MockResourceContext();
694  return resource_context_;
695}
696
697HostContentSettingsMap* TestingProfile::GetHostContentSettingsMap() {
698  if (!host_content_settings_map_.get()) {
699    host_content_settings_map_ = new HostContentSettingsMap(GetPrefs(), false);
700#if defined(ENABLE_EXTENSIONS)
701    ExtensionService* extension_service = GetExtensionService();
702    if (extension_service)
703      host_content_settings_map_->RegisterExtensionService(extension_service);
704#endif
705  }
706  return host_content_settings_map_.get();
707}
708
709content::GeolocationPermissionContext*
710TestingProfile::GetGeolocationPermissionContext() {
711  return ChromeGeolocationPermissionContextFactory::GetForProfile(this);
712}
713
714std::wstring TestingProfile::GetName() {
715  return std::wstring();
716}
717
718std::wstring TestingProfile::GetID() {
719  return id_;
720}
721
722void TestingProfile::SetID(const std::wstring& id) {
723  id_ = id;
724}
725
726bool TestingProfile::IsSameProfile(Profile *p) {
727  return this == p;
728}
729
730base::Time TestingProfile::GetStartTime() const {
731  return start_time_;
732}
733
734base::FilePath TestingProfile::last_selected_directory() {
735  return last_selected_directory_;
736}
737
738void TestingProfile::set_last_selected_directory(const base::FilePath& path) {
739  last_selected_directory_ = path;
740}
741
742PrefProxyConfigTracker* TestingProfile::GetProxyConfigTracker() {
743  if (!pref_proxy_config_tracker_.get()) {
744    // TestingProfile is used in unit tests, where local state is not available.
745    pref_proxy_config_tracker_.reset(
746        ProxyServiceFactory::CreatePrefProxyConfigTrackerOfProfile(GetPrefs(),
747                                                                   NULL));
748  }
749  return pref_proxy_config_tracker_.get();
750}
751
752void TestingProfile::BlockUntilHistoryProcessesPendingRequests() {
753  HistoryService* history_service =
754      HistoryServiceFactory::GetForProfile(this, Profile::EXPLICIT_ACCESS);
755  DCHECK(history_service);
756  DCHECK(base::MessageLoop::current());
757
758  CancelableRequestConsumer consumer;
759  history_service->ScheduleDBTask(new QuittingHistoryDBTask(), &consumer);
760  base::MessageLoop::current()->Run();
761}
762
763chrome_browser_net::Predictor* TestingProfile::GetNetworkPredictor() {
764  return NULL;
765}
766
767void TestingProfile::ClearNetworkingHistorySince(
768    base::Time time,
769    const base::Closure& completion) {
770  if (!completion.is_null()) {
771    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, completion);
772  }
773}
774
775GURL TestingProfile::GetHomePage() {
776  return GURL(chrome::kChromeUINewTabURL);
777}
778
779PrefService* TestingProfile::GetOffTheRecordPrefs() {
780  return NULL;
781}
782
783quota::SpecialStoragePolicy* TestingProfile::GetSpecialStoragePolicy() {
784  return GetExtensionSpecialStoragePolicy();
785}
786
787bool TestingProfile::WasCreatedByVersionOrLater(const std::string& version) {
788  return true;
789}
790
791bool TestingProfile::IsGuestSession() const {
792  return false;
793}
794Profile::ExitType TestingProfile::GetLastSessionExitType() {
795  return last_session_exited_cleanly_ ? EXIT_NORMAL : EXIT_CRASHED;
796}
797
798TestingProfile::Builder::Builder()
799    : build_called_(false),
800      delegate_(NULL) {
801}
802
803TestingProfile::Builder::~Builder() {
804}
805
806void TestingProfile::Builder::SetPath(const base::FilePath& path) {
807  path_ = path;
808}
809
810void TestingProfile::Builder::SetDelegate(Delegate* delegate) {
811  delegate_ = delegate;
812}
813
814void TestingProfile::Builder::SetExtensionSpecialStoragePolicy(
815    scoped_refptr<ExtensionSpecialStoragePolicy> policy) {
816  extension_policy_ = policy;
817}
818
819void TestingProfile::Builder::SetPrefService(
820    scoped_ptr<PrefServiceSyncable> prefs) {
821  pref_service_ = prefs.Pass();
822}
823
824scoped_ptr<TestingProfile> TestingProfile::Builder::Build() {
825  DCHECK(!build_called_);
826  build_called_ = true;
827  return scoped_ptr<TestingProfile>(new TestingProfile(
828      path_,
829      delegate_,
830      extension_policy_,
831      pref_service_.Pass()));
832}
833