1// Copyright 2014 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#ifndef COMPONENTS_KEYED_SERVICE_CONTENT_REFCOUNTED_BROWSER_CONTEXT_KEYED_SERVICE_H_
6#define COMPONENTS_KEYED_SERVICE_CONTENT_REFCOUNTED_BROWSER_CONTEXT_KEYED_SERVICE_H_
7
8#include "base/memory/ref_counted.h"
9#include "base/sequenced_task_runner_helpers.h"
10#include "components/keyed_service/core/keyed_service_export.h"
11#include "content/public/browser/browser_thread.h"
12
13class RefcountedBrowserContextKeyedService;
14
15namespace impl {
16
17struct KEYED_SERVICE_EXPORT RefcountedBrowserContextKeyedServiceTraits {
18  static void Destruct(const RefcountedBrowserContextKeyedService* obj);
19};
20
21}  // namespace impl
22
23// Base class for refcounted objects that hang off the BrowserContext.
24//
25// The two pass shutdown described in KeyedService works a bit differently
26// because there could be outstanding references on other threads.
27// ShutdownOnUIThread() will be called on the UI thread, and then the
28// destructor will run when the last reference is dropped, which may or may not
29// be after the corresponding BrowserContext has been destroyed.
30//
31// Optionally, if you initialize your service with the constructor that takes a
32// thread ID, your service will be deleted on that thread. We can't use
33// content::DeleteOnThread<> directly because
34// RefcountedBrowserContextKeyedService must be one type that
35// RefcountedBrowserContextKeyedServiceFactory can use.
36class KEYED_SERVICE_EXPORT RefcountedBrowserContextKeyedService
37    : public base::RefCountedThreadSafe<
38          RefcountedBrowserContextKeyedService,
39          impl::RefcountedBrowserContextKeyedServiceTraits> {
40 public:
41  // Unlike KeyedService, ShutdownOnUI is not optional. You must do something
42  // to drop references during the first pass Shutdown() because this is the
43  // only point where you are guaranteed that something is running on the UI
44  // thread. The PKSF framework will ensure that this is only called on the UI
45  // thread; you do not need to check for that yourself.
46  virtual void ShutdownOnUIThread() = 0;
47
48 protected:
49  // If your service does not need to be deleted on a specific thread, use the
50  // default constructor.
51  RefcountedBrowserContextKeyedService();
52
53  // If you need your service to be deleted on a specific thread (for example,
54  // you're converting a service that used content::DeleteOnThread<IO>), then
55  // use this constructor with the ID of the thread.
56  explicit RefcountedBrowserContextKeyedService(
57      const content::BrowserThread::ID thread_id);
58
59  // The second pass destruction can happen anywhere unless you specify which
60  // thread this service must be destroyed on by using the second constructor.
61  virtual ~RefcountedBrowserContextKeyedService();
62
63 private:
64  friend struct impl::RefcountedBrowserContextKeyedServiceTraits;
65  friend class base::DeleteHelper<RefcountedBrowserContextKeyedService>;
66  friend class base::RefCountedThreadSafe<
67      RefcountedBrowserContextKeyedService,
68      impl::RefcountedBrowserContextKeyedServiceTraits>;
69
70  // Do we have to delete this object on a specific thread?
71  bool requires_destruction_on_thread_;
72  content::BrowserThread::ID thread_id_;
73};
74
75#endif  // COMPONENTS_KEYED_SERVICE_CONTENT_REFCOUNTED_BROWSER_CONTEXT_KEYED_SERVICE_H_
76