| OLD | NEW |
| 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 } | |
| OLD | NEW |