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#include "content/public/browser/desktop_media_id.h"
6
7#include <vector>
8
9#include "base/memory/singleton.h"
10#include "base/strings/string_split.h"
11
12#if defined(USE_AURA)
13#include "ui/aura/window.h"
14#include "ui/aura/window_observer.h"
15#endif  // defined(USE_AURA)
16
17namespace  {
18
19#if defined(USE_AURA)
20
21class AuraWindowRegistry : public aura::WindowObserver {
22 public:
23  static AuraWindowRegistry* GetInstance() {
24    return Singleton<AuraWindowRegistry>::get();
25  }
26
27  int RegisterWindow(aura::Window* window) {
28    // First check if an Id is already assigned to the |window|.
29    std::map<aura::Window*, int>::iterator it = window_to_id_map_.find(window);
30    if (it != window_to_id_map_.end()) {
31      return it->second;
32    }
33
34    // If the windows doesn't have an Id yet assign it.
35    int id;
36    do {
37      id = next_id_;
38      next_id_ = (next_id_ == INT_MAX) ? 1 : (next_id_ + 1);
39    } while (id_to_window_map_.find(id) != id_to_window_map_.end());
40
41    window_to_id_map_[window] = id;
42    id_to_window_map_[id] = window;
43    window->AddObserver(this);
44    return id;
45  }
46
47  aura::Window* GetWindowById(int id) {
48    std::map<int, aura::Window*>::iterator it = id_to_window_map_.find(id);
49    return (it != id_to_window_map_.end()) ? it->second : NULL;
50  }
51
52 private:
53  friend struct DefaultSingletonTraits<AuraWindowRegistry>;
54
55  AuraWindowRegistry()
56      : next_id_(1) {
57  }
58  virtual ~AuraWindowRegistry() {}
59
60  // WindowObserver overrides.
61  virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
62    std::map<aura::Window*, int>::iterator it = window_to_id_map_.find(window);
63    DCHECK(it != window_to_id_map_.end());
64    id_to_window_map_.erase(it->second);
65    window_to_id_map_.erase(it);
66  }
67
68  int next_id_;
69  std::map<aura::Window*, int> window_to_id_map_;
70  std::map<int, aura::Window*> id_to_window_map_;
71
72  DISALLOW_COPY_AND_ASSIGN(AuraWindowRegistry);
73};
74
75#endif  // defined(USE_AURA)
76
77}  // namespace
78
79namespace content {
80
81const char kScreenPrefix[] = "screen";
82const char kWindowPrefix[] = "window";
83const char kAuraWindowPrefix[] = "aura_window";
84
85#if defined(USE_AURA)
86
87// static
88DesktopMediaID DesktopMediaID::RegisterAuraWindow(aura::Window* window) {
89  return DesktopMediaID(
90      TYPE_AURA_WINDOW,
91      AuraWindowRegistry::GetInstance()->RegisterWindow(window));
92}
93
94// static
95aura::Window* DesktopMediaID::GetAuraWindowById(const DesktopMediaID& id) {
96  DCHECK_EQ(id.type, TYPE_AURA_WINDOW);
97  return AuraWindowRegistry::GetInstance()->GetWindowById(id.id);
98}
99
100#endif  // defined(USE_AURA)
101
102// static
103DesktopMediaID DesktopMediaID::Parse(const std::string& str) {
104  std::vector<std::string> parts;
105  base::SplitString(str, ':', &parts);
106
107  if (parts.size() != 2)
108    return DesktopMediaID(TYPE_NONE, 0);
109
110  Type type = TYPE_NONE;
111  if (parts[0] == kScreenPrefix) {
112    type = TYPE_SCREEN;
113  } else if (parts[0] == kWindowPrefix) {
114    type = TYPE_WINDOW;
115  } else if (parts[0] == kAuraWindowPrefix) {
116    type = TYPE_AURA_WINDOW;
117  } else {
118    return DesktopMediaID(TYPE_NONE, 0);
119  }
120
121  int64 id;
122  if (!base::StringToInt64(parts[1], &id))
123    return DesktopMediaID(TYPE_NONE, 0);
124
125  return DesktopMediaID(type, id);
126}
127
128std::string DesktopMediaID::ToString() {
129  std::string prefix;
130  switch (type) {
131    case TYPE_NONE:
132      NOTREACHED();
133      return std::string();
134    case TYPE_SCREEN:
135      prefix = kScreenPrefix;
136      break;
137    case TYPE_WINDOW:
138      prefix = kWindowPrefix;
139      break;
140    case TYPE_AURA_WINDOW:
141      prefix = kAuraWindowPrefix;
142      break;
143  }
144  DCHECK(!prefix.empty());
145
146  prefix.append(":");
147  prefix.append(base::Int64ToString(id));
148
149  return prefix;
150}
151
152}  // namespace content
153