1// Copyright 2013 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 IOS_PUBLIC_PROVIDER_WEB_WEB_STATE_USER_DATA_H_
6#define IOS_PUBLIC_PROVIDER_WEB_WEB_STATE_USER_DATA_H_
7
8#include "ios/public/consumer/base/supports_user_data.h"
9#include "ios/public/provider/web/web_state.h"
10
11namespace ios {
12
13// A base class for classes attached to, and scoped to, the lifetime of a
14// WebState. For example:
15//
16// --- in foo.h ---
17// class Foo : public ios::WebStateUserData<Foo> {
18//  public:
19//   virtual ~Foo();
20//   // ... more public stuff here ...
21//  private:
22//   explicit Foo(ios::WebState* web_state);
23//   friend class ios::WebStateUserData<Foo>;
24//   // ... more private stuff here ...
25// }
26// --- in foo.cc ---
27// DEFINE_WEB_CONTENTS_USER_DATA_KEY(Foo);
28//
29template <typename T>
30class WebStateUserData : public ios::SupportsUserData::Data {
31 public:
32  // Creates an object of type T, and attaches it to the specified WebState.
33  // If an instance is already attached, does nothing.
34  static void CreateForWebState(WebState* web_state) {
35    if (!FromWebState(web_state))
36      web_state->SetUserData(UserDataKey(), new T(web_state));
37  }
38
39  // Retrieves the instance of type T that was attached to the specified
40  // WebState (via CreateForWebState above) and returns it. If no instance
41  // of the type was attached, returns NULL.
42  static T* FromWebState(WebState* web_state) {
43    return static_cast<T*>(web_state->GetUserData(UserDataKey()));
44  }
45  static const T* FromWebState(const WebState* web_state) {
46    return static_cast<const T*>(web_state->GetUserData(UserDataKey()));
47  }
48
49 protected:
50  static inline void* UserDataKey() {
51    return &kLocatorKey;
52  }
53
54 private:
55  // The user data key.
56  static int kLocatorKey;
57};
58
59// The macro to define the locator key. This key should be defined in the .cc
60// file of the derived class.
61//
62// The "= 0" is surprising, but is required to effect a definition rather than
63// a declaration. Without it, this would be merely a declaration of a template
64// specialization. (C++98: 14.7.3.15; C++11: 14.7.3.13)
65//
66#define DEFINE_WEB_STATE_USER_DATA_KEY(TYPE) \
67template<>                                      \
68int ios::WebStateUserData<TYPE>::kLocatorKey = 0
69
70}  // namespace ios
71
72#endif  // IOS_PUBLIC_PROVIDER_WEB_WEB_STATE_USER_DATA_H_
73