Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync_file_system / local / local_file_sync_status.cc
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 "chrome/browser/sync_file_system/local/local_file_sync_status.h"
6
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "webkit/common/fileapi/file_system_util.h"
10
11 using fileapi::FileSystemURL;
12 using fileapi::FileSystemURLSet;
13
14 namespace sync_file_system {
15
16 namespace {
17
18 typedef LocalFileSyncStatus::OriginAndType OriginAndType;
19
20 OriginAndType GetOriginAndType(const fileapi::FileSystemURL& url) {
21   return std::make_pair(url.origin(), url.type());
22 }
23
24 base::FilePath NormalizePath(const base::FilePath& path) {
25   // Ensure |path| has single trailing path-separator, so that we can use
26   // prefix-match to find descendants of |path| in an ordered container.
27   return base::FilePath(path.StripTrailingSeparators().value() +
28                         fileapi::VirtualPath::kSeparator);
29 }
30
31 struct SetKeyHelper {
32   template <typename Iterator>
33   static const base::FilePath& GetKey(Iterator itr) {
34     return *itr;
35   }
36 };
37
38 struct MapKeyHelper {
39   template <typename Iterator>
40   static const base::FilePath& GetKey(Iterator itr) {
41     return itr->first;
42   }
43 };
44
45 template <typename Container, typename GetKeyHelper>
46 bool ContainsChildOrParent(const Container& paths,
47                            const base::FilePath& path,
48                            const GetKeyHelper& get_key_helper) {
49   base::FilePath normalized_path = NormalizePath(path);
50
51   // Check if |paths| has a child of |normalized_path|.
52   // Note that descendants of |normalized_path| are stored right after
53   // |normalized_path| since |normalized_path| has trailing path separator.
54   typename Container::const_iterator upper =
55       paths.upper_bound(normalized_path);
56
57   if (upper != paths.end() &&
58       normalized_path.IsParent(get_key_helper.GetKey(upper)))
59     return true;
60
61   // Check if any ancestor of |normalized_path| is in |writing_|.
62   while (true) {
63     if (ContainsKey(paths, normalized_path))
64       return true;
65
66     if (fileapi::VirtualPath::IsRootPath(normalized_path))
67       return false;
68
69     normalized_path =
70         NormalizePath(fileapi::VirtualPath::DirName(normalized_path));
71   }
72 }
73
74 }  // namespace
75
76 LocalFileSyncStatus::LocalFileSyncStatus() {}
77
78 LocalFileSyncStatus::~LocalFileSyncStatus() {}
79
80 void LocalFileSyncStatus::StartWriting(const FileSystemURL& url) {
81   DCHECK(CalledOnValidThread());
82   DCHECK(!IsChildOrParentSyncing(url));
83   writing_[GetOriginAndType(url)][NormalizePath(url.path())]++;
84 }
85
86 void LocalFileSyncStatus::EndWriting(const FileSystemURL& url) {
87   DCHECK(CalledOnValidThread());
88   base::FilePath normalized_path = NormalizePath(url.path());
89   OriginAndType origin_and_type = GetOriginAndType(url);
90
91   int count = --writing_[origin_and_type][normalized_path];
92   if (count == 0) {
93     writing_[origin_and_type].erase(normalized_path);
94     if (writing_[origin_and_type].empty())
95       writing_.erase(origin_and_type);
96     FOR_EACH_OBSERVER(Observer, observer_list_, OnSyncEnabled(url));
97   }
98 }
99
100 void LocalFileSyncStatus::StartSyncing(const FileSystemURL& url) {
101   DCHECK(CalledOnValidThread());
102   DCHECK(!IsChildOrParentWriting(url));
103   DCHECK(!IsChildOrParentSyncing(url));
104   syncing_[GetOriginAndType(url)].insert(NormalizePath(url.path()));
105 }
106
107 void LocalFileSyncStatus::EndSyncing(const FileSystemURL& url) {
108   DCHECK(CalledOnValidThread());
109   base::FilePath normalized_path = NormalizePath(url.path());
110   OriginAndType origin_and_type = GetOriginAndType(url);
111
112   syncing_[origin_and_type].erase(normalized_path);
113   if (syncing_[origin_and_type].empty())
114     syncing_.erase(origin_and_type);
115   FOR_EACH_OBSERVER(Observer, observer_list_, OnSyncEnabled(url));
116   FOR_EACH_OBSERVER(Observer, observer_list_, OnWriteEnabled(url));
117 }
118
119 bool LocalFileSyncStatus::IsWriting(const FileSystemURL& url) const {
120   DCHECK(CalledOnValidThread());
121   return IsChildOrParentWriting(url);
122 }
123
124 bool LocalFileSyncStatus::IsWritable(const FileSystemURL& url) const {
125   DCHECK(CalledOnValidThread());
126   return !IsChildOrParentSyncing(url);
127 }
128
129 bool LocalFileSyncStatus::IsSyncable(const FileSystemURL& url) const {
130   DCHECK(CalledOnValidThread());
131   return !IsChildOrParentSyncing(url) && !IsChildOrParentWriting(url);
132 }
133
134 void LocalFileSyncStatus::AddObserver(Observer* observer) {
135   DCHECK(CalledOnValidThread());
136   observer_list_.AddObserver(observer);
137 }
138
139 void LocalFileSyncStatus::RemoveObserver(Observer* observer) {
140   DCHECK(CalledOnValidThread());
141   observer_list_.RemoveObserver(observer);
142 }
143
144 bool LocalFileSyncStatus::IsChildOrParentWriting(
145     const FileSystemURL& url) const {
146   DCHECK(CalledOnValidThread());
147
148   URLBucket::const_iterator found = writing_.find(GetOriginAndType(url));
149   if (found == writing_.end())
150     return false;
151   return ContainsChildOrParent(found->second, url.path(),
152                                MapKeyHelper());
153 }
154
155 bool LocalFileSyncStatus::IsChildOrParentSyncing(
156     const FileSystemURL& url) const {
157   DCHECK(CalledOnValidThread());
158   URLSet::const_iterator found = syncing_.find(GetOriginAndType(url));
159   if (found == syncing_.end())
160     return false;
161   return ContainsChildOrParent(found->second, url.path(),
162                                SetKeyHelper());
163 }
164
165 }  // namespace sync_file_system