Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: chrome/browser/privacy_blacklist/blacklist_manager.cc

Issue 361030: Fix threading issues in BlacklistManager, using new ChromeThread. (Closed)
Patch Set: fix compile after the dtor has been made private Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/privacy_blacklist/blacklist_manager.h" 5 #include "chrome/browser/privacy_blacklist/blacklist_manager.h"
6 6
7 #include "base/message_loop.h" 7 #include "base/message_loop.h"
8 #include "base/string_util.h" 8 #include "base/string_util.h"
9 #include "base/task.h" 9 #include "base/task.h"
10 #include "base/thread.h" 10 #include "base/thread.h"
11 #include "chrome/browser/privacy_blacklist/blacklist.h" 11 #include "chrome/browser/privacy_blacklist/blacklist.h"
12 #include "chrome/browser/privacy_blacklist/blacklist_io.h" 12 #include "chrome/browser/privacy_blacklist/blacklist_io.h"
13 #include "chrome/browser/profile.h" 13 #include "chrome/browser/profile.h"
14 #include "chrome/common/chrome_constants.h" 14 #include "chrome/common/chrome_constants.h"
15 #include "chrome/common/notification_service.h" 15 #include "chrome/common/notification_service.h"
16 #include "chrome/common/notification_source.h" 16 #include "chrome/common/notification_source.h"
17 #include "chrome/common/notification_type.h" 17 #include "chrome/common/notification_type.h"
18 18
19 // Base class for tasks that use BlacklistManager. It ensures that the
20 // BlacklistManager won't get destroyed while we need it, and that it
21 // will be destroyed always on the same thread. That's why we use
22 // a custom Task instead of just NewRunnableMethod.
23 class BlacklistManagerTask : public Task {
24 public:
25 explicit BlacklistManagerTask(BlacklistManager* manager)
26 : original_loop_(MessageLoop::current()),
27 manager_(manager) {
28 DCHECK(original_loop_);
29 manager->AddRef();
30 }
31
32 ~BlacklistManagerTask() {
33 original_loop_->ReleaseSoon(FROM_HERE, manager_);
34 }
35
36 protected:
37 BlacklistManager* blacklist_manager() const { return manager_; }
38
39 MessageLoop* original_loop_;
40
41 private:
42 BlacklistManager* manager_;
43
44 DISALLOW_COPY_AND_ASSIGN(BlacklistManagerTask);
45 };
46
47 BlacklistPathProvider::~BlacklistPathProvider() { 19 BlacklistPathProvider::~BlacklistPathProvider() {
48 } 20 }
49 21
50 class BlacklistManager::CompileBlacklistTask : public BlacklistManagerTask {
51 public:
52 CompileBlacklistTask(BlacklistManager* manager,
53 const FilePath& destination_blacklist,
54 const std::vector<FilePath>& source_blacklists)
55 : BlacklistManagerTask(manager),
56 destination_blacklist_(destination_blacklist),
57 source_blacklists_(source_blacklists) {
58 }
59
60 virtual void Run() {
61 bool success = true;
62
63 Blacklist blacklist;
64 std::string error_string;
65
66 for (std::vector<FilePath>::const_iterator i = source_blacklists_.begin();
67 i != source_blacklists_.end(); ++i) {
68 if (!BlacklistIO::ReadText(&blacklist, *i, &error_string)) {
69 success = false;
70 break;
71 }
72 }
73
74 // Only overwrite the current compiled blacklist if we read all source
75 // files successfully.
76 if (success)
77 success = BlacklistIO::WriteBinary(&blacklist, destination_blacklist_);
78
79 original_loop_->PostTask(
80 FROM_HERE,
81 NewRunnableMethod(blacklist_manager(),
82 &BlacklistManager::OnBlacklistCompilationFinished,
83 success));
84 }
85
86 private:
87 FilePath destination_blacklist_;
88
89 std::vector<FilePath> source_blacklists_;
90
91 DISALLOW_COPY_AND_ASSIGN(CompileBlacklistTask);
92 };
93
94 class BlacklistManager::ReadBlacklistTask : public BlacklistManagerTask {
95 public:
96 ReadBlacklistTask(BlacklistManager* manager,
97 const FilePath& compiled_blacklist,
98 const std::vector<FilePath>& transient_blacklists)
99 : BlacklistManagerTask(manager),
100 compiled_blacklist_(compiled_blacklist),
101 transient_blacklists_(transient_blacklists) {
102 }
103
104 virtual void Run() {
105 scoped_ptr<Blacklist> blacklist(new Blacklist);
106 if (!BlacklistIO::ReadBinary(blacklist.get(), compiled_blacklist_)) {
107 ReportReadResult(NULL);
108 return;
109 }
110
111 std::string error_string;
112 std::vector<FilePath>::const_iterator i;
113 for (i = transient_blacklists_.begin();
114 i != transient_blacklists_.end(); ++i) {
115 if (!BlacklistIO::ReadText(blacklist.get(), *i, &error_string)) {
116 ReportReadResult(NULL);
117 return;
118 }
119 }
120
121 ReportReadResult(blacklist.release());
122 }
123
124 private:
125 void ReportReadResult(Blacklist* blacklist) {
126 original_loop_->PostTask(
127 FROM_HERE, NewRunnableMethod(blacklist_manager(),
128 &BlacklistManager::OnBlacklistReadFinished,
129 blacklist));
130 }
131
132 FilePath compiled_blacklist_;
133 std::vector<FilePath> transient_blacklists_;
134
135 DISALLOW_COPY_AND_ASSIGN(ReadBlacklistTask);
136 };
137
138 BlacklistManager::BlacklistManager(Profile* profile, 22 BlacklistManager::BlacklistManager(Profile* profile,
139 BlacklistPathProvider* path_provider, 23 BlacklistPathProvider* path_provider)
140 base::Thread* backend_thread)
141 : first_read_finished_(false), 24 : first_read_finished_(false),
142 profile_(profile), 25 profile_(profile),
143 compiled_blacklist_path_( 26 compiled_blacklist_path_(
144 profile->GetPath().Append(chrome::kPrivacyBlacklistFileName)), 27 profile->GetPath().Append(chrome::kPrivacyBlacklistFileName)),
145 path_provider_(path_provider), 28 path_provider_(path_provider) {
146 backend_thread_(backend_thread) { 29 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
30
147 registrar_.Add(this, 31 registrar_.Add(this,
148 NotificationType::EXTENSION_LOADED, 32 NotificationType::EXTENSION_LOADED,
149 Source<Profile>(profile)); 33 Source<Profile>(profile));
150 registrar_.Add(this, 34 registrar_.Add(this,
151 NotificationType::EXTENSION_UNLOADED, 35 NotificationType::EXTENSION_UNLOADED,
152 Source<Profile>(profile)); 36 Source<Profile>(profile));
153 ReadBlacklist(); 37 ReadBlacklist();
154 } 38 }
155 39
156 void BlacklistManager::Observe(NotificationType type, 40 void BlacklistManager::Observe(NotificationType type,
157 const NotificationSource& source, 41 const NotificationSource& source,
158 const NotificationDetails& details) { 42 const NotificationDetails& details) {
43 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
44
159 switch (type.value) { 45 switch (type.value) {
160 case NotificationType::EXTENSION_LOADED: 46 case NotificationType::EXTENSION_LOADED:
161 case NotificationType::EXTENSION_UNLOADED: 47 case NotificationType::EXTENSION_UNLOADED:
162 CompileBlacklist(); 48 CompileBlacklist();
163 break; 49 break;
164 default: 50 default:
165 NOTREACHED(); 51 NOTREACHED();
166 break; 52 break;
167 } 53 }
168 } 54 }
169 55
170 void BlacklistManager::CompileBlacklist() { 56 void BlacklistManager::CompileBlacklist() {
171 DCHECK(CalledOnValidThread()); 57 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
172 58
173 RunTaskOnBackendThread(new CompileBlacklistTask( 59 ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE,
174 this, compiled_blacklist_path_, 60 NewRunnableMethod(this, &BlacklistManager::DoCompileBlacklist,
175 path_provider_->GetPersistentBlacklistPaths())); 61 path_provider_->GetPersistentBlacklistPaths()));
176 } 62 }
177 63
178 void BlacklistManager::ReadBlacklist() { 64 void BlacklistManager::DoCompileBlacklist(
179 DCHECK(CalledOnValidThread()); 65 const std::vector<FilePath>& source_blacklists) {
66 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
180 67
181 RunTaskOnBackendThread(new ReadBlacklistTask( 68 bool success = true;
182 this, compiled_blacklist_path_, 69
183 path_provider_->GetTransientBlacklistPaths())); 70 Blacklist blacklist;
71 std::string error_string;
72
73 for (std::vector<FilePath>::const_iterator i = source_blacklists.begin();
74 i != source_blacklists.end(); ++i) {
75 if (!BlacklistIO::ReadText(&blacklist, *i, &error_string)) {
76 success = false;
77 break;
78 }
79 }
80
81 // Only overwrite the current compiled blacklist if we read all source
82 // files successfully.
83 if (success)
84 success = BlacklistIO::WriteBinary(&blacklist, compiled_blacklist_path_);
85
86 ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
87 NewRunnableMethod(this, &BlacklistManager::OnBlacklistCompilationFinished,
88 success));
184 } 89 }
185 90
186 void BlacklistManager::OnBlacklistCompilationFinished(bool success) { 91 void BlacklistManager::OnBlacklistCompilationFinished(bool success) {
187 DCHECK(CalledOnValidThread()); 92 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
188 93
189 if (success) { 94 if (success) {
190 ReadBlacklist(); 95 ReadBlacklist();
191 } else { 96 } else {
192 string16 error_message(ASCIIToUTF16("Blacklist compilation failed.")); 97 string16 error_message(ASCIIToUTF16("Blacklist compilation failed."));
193 NotificationService::current()->Notify( 98 NotificationService::current()->Notify(
194 NotificationType::BLACKLIST_MANAGER_ERROR, 99 NotificationType::BLACKLIST_MANAGER_ERROR,
195 Source<Profile>(profile_), 100 Source<Profile>(profile_),
196 Details<string16>(&error_message)); 101 Details<string16>(&error_message));
197 } 102 }
198 } 103 }
199 104
105 void BlacklistManager::ReadBlacklist() {
106 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
107
108 ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE,
109 NewRunnableMethod(this, &BlacklistManager::DoReadBlacklist,
110 path_provider_->GetTransientBlacklistPaths()));
111 }
112
113 void BlacklistManager::DoReadBlacklist(
114 const std::vector<FilePath>& transient_blacklists) {
115 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
116
117 scoped_ptr<Blacklist> blacklist(new Blacklist);
118 if (!BlacklistIO::ReadBinary(blacklist.get(), compiled_blacklist_path_)) {
119 ReportBlacklistReadResult(NULL);
120 return;
121 }
122
123 std::string error_string;
124 std::vector<FilePath>::const_iterator i;
125 for (i = transient_blacklists.begin();
126 i != transient_blacklists.end(); ++i) {
127 if (!BlacklistIO::ReadText(blacklist.get(), *i, &error_string)) {
128 ReportBlacklistReadResult(NULL);
129 return;
130 }
131 }
132
133 ReportBlacklistReadResult(blacklist.release());
134 }
135
136 void BlacklistManager::ReportBlacklistReadResult(Blacklist* blacklist) {
137 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
138 ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
139 NewRunnableMethod(this, &BlacklistManager::OnBlacklistReadFinished,
140 blacklist));
141 }
142
200 void BlacklistManager::OnBlacklistReadFinished(Blacklist* blacklist) { 143 void BlacklistManager::OnBlacklistReadFinished(Blacklist* blacklist) {
201 DCHECK(CalledOnValidThread()); 144 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
202 145
203 if (!blacklist) { 146 if (!blacklist) {
204 if (!first_read_finished_) { 147 if (!first_read_finished_) {
205 // If we're loading for the first time, the compiled blacklist could 148 // If we're loading for the first time, the compiled blacklist could
206 // just not exist. Try compiling it once. 149 // just not exist. Try compiling it once.
207 first_read_finished_ = true; 150 first_read_finished_ = true;
208 CompileBlacklist(); 151 CompileBlacklist();
209 } else { 152 } else {
210 string16 error_message(ASCIIToUTF16("Blacklist read failed.")); 153 string16 error_message(ASCIIToUTF16("Blacklist read failed."));
211 NotificationService::current()->Notify( 154 NotificationService::current()->Notify(
212 NotificationType::BLACKLIST_MANAGER_ERROR, 155 NotificationType::BLACKLIST_MANAGER_ERROR,
213 Source<Profile>(profile_), 156 Source<Profile>(profile_),
214 Details<string16>(&error_message)); 157 Details<string16>(&error_message));
215 } 158 }
216 return; 159 return;
217 } 160 }
218 first_read_finished_ = true; 161 first_read_finished_ = true;
219 compiled_blacklist_.reset(blacklist); 162 compiled_blacklist_.reset(blacklist);
220 163
221 NotificationService::current()->Notify( 164 NotificationService::current()->Notify(
222 NotificationType::BLACKLIST_MANAGER_BLACKLIST_READ_FINISHED, 165 NotificationType::BLACKLIST_MANAGER_BLACKLIST_READ_FINISHED,
223 Source<Profile>(profile_), 166 Source<Profile>(profile_),
224 Details<Blacklist>(blacklist)); 167 Details<Blacklist>(blacklist));
225 } 168 }
226
227 void BlacklistManager::RunTaskOnBackendThread(Task* task) {
228 if (backend_thread_) {
229 backend_thread_->message_loop()->PostTask(FROM_HERE, task);
230 } else {
231 task->Run();
232 delete task;
233 }
234 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698