Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/extensions/api/history/history_api.h" | 5 #include "chrome/browser/extensions/api/history/history_api.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 212 } | 212 } |
| 213 | 213 |
| 214 void HistoryAPI::OnListenerAdded(const EventListenerInfo& details) { | 214 void HistoryAPI::OnListenerAdded(const EventListenerInfo& details) { |
| 215 Profile* profile = Profile::FromBrowserContext(browser_context_); | 215 Profile* profile = Profile::FromBrowserContext(browser_context_); |
| 216 history_event_router_.reset(new HistoryEventRouter( | 216 history_event_router_.reset(new HistoryEventRouter( |
| 217 profile, HistoryServiceFactory::GetForProfile( | 217 profile, HistoryServiceFactory::GetForProfile( |
| 218 profile, ServiceAccessType::EXPLICIT_ACCESS))); | 218 profile, ServiceAccessType::EXPLICIT_ACCESS))); |
| 219 EventRouter::Get(browser_context_)->UnregisterObserver(this); | 219 EventRouter::Get(browser_context_)->UnregisterObserver(this); |
| 220 } | 220 } |
| 221 | 221 |
| 222 bool HistoryFunction::ValidateUrl(const std::string& url_string, GURL* url) { | 222 bool HistoryFunction::ValidateUrl(const std::string& url_string, |
| 223 GURL* url, | |
| 224 std::string* error) { | |
| 223 GURL temp_url(url_string); | 225 GURL temp_url(url_string); |
| 224 if (!temp_url.is_valid()) { | 226 if (!temp_url.is_valid()) { |
| 225 error_ = kInvalidUrlError; | 227 *error = kInvalidUrlError; |
| 226 return false; | 228 return false; |
| 227 } | 229 } |
| 228 url->Swap(&temp_url); | 230 url->Swap(&temp_url); |
| 229 return true; | 231 return true; |
| 230 } | 232 } |
| 231 | 233 |
| 232 bool HistoryFunction::VerifyDeleteAllowed() { | 234 bool HistoryFunction::VerifyDeleteAllowed(std::string* error) { |
| 233 PrefService* prefs = GetProfile()->GetPrefs(); | 235 PrefService* prefs = GetProfile()->GetPrefs(); |
| 234 if (!prefs->GetBoolean(prefs::kAllowDeletingBrowserHistory)) { | 236 if (!prefs->GetBoolean(prefs::kAllowDeletingBrowserHistory)) { |
| 235 error_ = kDeleteProhibitedError; | 237 *error = kDeleteProhibitedError; |
| 236 return false; | 238 return false; |
| 237 } | 239 } |
| 238 return true; | 240 return true; |
| 239 } | 241 } |
| 240 | 242 |
| 241 base::Time HistoryFunction::GetTime(double ms_from_epoch) { | 243 base::Time HistoryFunction::GetTime(double ms_from_epoch) { |
| 242 // The history service has seconds resolution, while javascript Date() has | 244 // The history service has seconds resolution, while javascript Date() has |
| 243 // milliseconds resolution. | 245 // milliseconds resolution. |
| 244 double seconds_from_epoch = ms_from_epoch / 1000.0; | 246 double seconds_from_epoch = ms_from_epoch / 1000.0; |
| 245 // Time::FromDoubleT converts double time 0 to empty Time object. So we need | 247 // Time::FromDoubleT converts double time 0 to empty Time object. So we need |
| 246 // to do special handling here. | 248 // to do special handling here. |
| 247 return (seconds_from_epoch == 0) ? | 249 return (seconds_from_epoch == 0) ? |
| 248 base::Time::UnixEpoch() : base::Time::FromDoubleT(seconds_from_epoch); | 250 base::Time::UnixEpoch() : base::Time::FromDoubleT(seconds_from_epoch); |
| 249 } | 251 } |
| 250 | 252 |
| 251 HistoryFunctionWithCallback::HistoryFunctionWithCallback() { | 253 Profile* HistoryFunction::GetProfile() const { |
| 254 return Profile::FromBrowserContext(browser_context()); | |
| 252 } | 255 } |
| 253 | 256 |
| 254 HistoryFunctionWithCallback::~HistoryFunctionWithCallback() { | 257 HistoryFunctionWithCallback::HistoryFunctionWithCallback() {} |
| 258 | |
| 259 HistoryFunctionWithCallback::~HistoryFunctionWithCallback() {} | |
| 260 | |
| 261 void HistoryFunctionWithCallback::SendAsyncResponse( | |
|
Devlin
2017/02/03 22:30:53
Do we have to SendAsyncResponse in order to preven
lazyboy
2017/02/03 23:49:06
HistoryService apis run on its own TaskRunner, e.g
Devlin
2017/02/06 16:09:26
So if that's the case (that all these methods on h
lazyboy
2017/02/14 00:55:30
Done.
| |
| 262 ResponseValue response_value) { | |
| 263 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 264 FROM_HERE, | |
| 265 base::Bind(&HistoryFunctionWithCallback::SendResponseToCallback, this, | |
| 266 base::Passed(&response_value))); | |
| 255 } | 267 } |
| 256 | 268 |
| 257 bool HistoryFunctionWithCallback::RunAsync() { | 269 void HistoryFunctionWithCallback::SendResponseToCallback( |
| 258 AddRef(); // Balanced in SendAysncRepose() and below. | 270 ResponseValue response_value) { |
| 259 bool retval = RunAsyncImpl(); | 271 Respond(std::move(response_value)); |
| 260 if (false == retval) | 272 Release(); // Balanced in Run(). |
| 261 Release(); | |
| 262 return retval; | |
| 263 } | 273 } |
| 264 | 274 |
| 265 void HistoryFunctionWithCallback::SendAsyncResponse() { | 275 ExtensionFunction::ResponseAction HistoryGetVisitsFunction::Run() { |
| 266 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 267 FROM_HERE, | |
| 268 base::Bind(&HistoryFunctionWithCallback::SendResponseToCallback, this)); | |
| 269 } | |
| 270 | |
| 271 void HistoryFunctionWithCallback::SendResponseToCallback() { | |
| 272 SendResponse(true); | |
| 273 Release(); // Balanced in RunAsync(). | |
| 274 } | |
| 275 | |
| 276 bool HistoryGetVisitsFunction::RunAsyncImpl() { | |
| 277 std::unique_ptr<GetVisits::Params> params(GetVisits::Params::Create(*args_)); | 276 std::unique_ptr<GetVisits::Params> params(GetVisits::Params::Create(*args_)); |
| 278 EXTENSION_FUNCTION_VALIDATE(params.get()); | 277 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 279 | 278 |
| 280 GURL url; | 279 GURL url; |
| 281 if (!ValidateUrl(params->details.url, &url)) | 280 std::string error; |
| 282 return false; | 281 if (!ValidateUrl(params->details.url, &url, &error)) |
| 282 return RespondNow(Error(error)); | |
| 283 | 283 |
| 284 history::HistoryService* hs = HistoryServiceFactory::GetForProfile( | 284 history::HistoryService* hs = HistoryServiceFactory::GetForProfile( |
| 285 GetProfile(), ServiceAccessType::EXPLICIT_ACCESS); | 285 GetProfile(), ServiceAccessType::EXPLICIT_ACCESS); |
| 286 hs->QueryURL(url, | 286 hs->QueryURL(url, |
| 287 true, // Retrieve full history of a URL. | 287 true, // Retrieve full history of a URL. |
| 288 base::Bind(&HistoryGetVisitsFunction::QueryComplete, | 288 base::Bind(&HistoryGetVisitsFunction::QueryComplete, |
| 289 base::Unretained(this)), | 289 base::Unretained(this)), |
| 290 &task_tracker_); | 290 &task_tracker_); |
| 291 return true; | 291 AddRef(); // Balanced in SendAsyncResponse(). |
| 292 return RespondLater(); // QueryComplete() will be called asynchronously. | |
| 292 } | 293 } |
| 293 | 294 |
| 294 void HistoryGetVisitsFunction::QueryComplete( | 295 void HistoryGetVisitsFunction::QueryComplete( |
| 295 bool success, | 296 bool success, |
| 296 const history::URLRow& url_row, | 297 const history::URLRow& url_row, |
| 297 const history::VisitVector& visits) { | 298 const history::VisitVector& visits) { |
| 298 VisitItemList visit_item_vec; | 299 VisitItemList visit_item_vec; |
| 299 if (success && !visits.empty()) { | 300 if (success && !visits.empty()) { |
| 300 for (const history::VisitRow& visit : visits) | 301 for (const history::VisitRow& visit : visits) |
| 301 visit_item_vec.push_back(GetVisitItem(visit)); | 302 visit_item_vec.push_back(GetVisitItem(visit)); |
| 302 } | 303 } |
| 303 | 304 |
| 304 results_ = GetVisits::Results::Create(visit_item_vec); | 305 SendAsyncResponse(ArgumentList(GetVisits::Results::Create(visit_item_vec))); |
|
Devlin
2017/02/06 16:09:26
e.g. this becomes just:
Respond(ArgumentList(...))
lazyboy
2017/02/14 00:55:30
Done.
| |
| 305 SendAsyncResponse(); | |
| 306 } | 306 } |
| 307 | 307 |
| 308 bool HistorySearchFunction::RunAsyncImpl() { | 308 ExtensionFunction::ResponseAction HistorySearchFunction::Run() { |
| 309 std::unique_ptr<Search::Params> params(Search::Params::Create(*args_)); | 309 std::unique_ptr<Search::Params> params(Search::Params::Create(*args_)); |
| 310 EXTENSION_FUNCTION_VALIDATE(params.get()); | 310 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 311 | 311 |
| 312 base::string16 search_text = base::UTF8ToUTF16(params->query.text); | 312 base::string16 search_text = base::UTF8ToUTF16(params->query.text); |
| 313 | 313 |
| 314 history::QueryOptions options; | 314 history::QueryOptions options; |
| 315 options.SetRecentDayRange(1); | 315 options.SetRecentDayRange(1); |
| 316 options.max_count = 100; | 316 options.max_count = 100; |
| 317 | 317 |
| 318 if (params->query.start_time.get()) | 318 if (params->query.start_time.get()) |
| 319 options.begin_time = GetTime(*params->query.start_time); | 319 options.begin_time = GetTime(*params->query.start_time); |
| 320 if (params->query.end_time.get()) | 320 if (params->query.end_time.get()) |
| 321 options.end_time = GetTime(*params->query.end_time); | 321 options.end_time = GetTime(*params->query.end_time); |
| 322 if (params->query.max_results.get()) | 322 if (params->query.max_results.get()) |
| 323 options.max_count = *params->query.max_results; | 323 options.max_count = *params->query.max_results; |
| 324 | 324 |
| 325 history::HistoryService* hs = HistoryServiceFactory::GetForProfile( | 325 history::HistoryService* hs = HistoryServiceFactory::GetForProfile( |
| 326 GetProfile(), ServiceAccessType::EXPLICIT_ACCESS); | 326 GetProfile(), ServiceAccessType::EXPLICIT_ACCESS); |
| 327 hs->QueryHistory(search_text, | 327 hs->QueryHistory(search_text, |
| 328 options, | 328 options, |
| 329 base::Bind(&HistorySearchFunction::SearchComplete, | 329 base::Bind(&HistorySearchFunction::SearchComplete, |
| 330 base::Unretained(this)), | 330 base::Unretained(this)), |
| 331 &task_tracker_); | 331 &task_tracker_); |
| 332 | 332 |
| 333 return true; | 333 AddRef(); // Balanced in SendAsyncResponse(). |
| 334 return RespondLater(); // SearchComplete() will be called asynchronously. | |
| 334 } | 335 } |
| 335 | 336 |
| 336 void HistorySearchFunction::SearchComplete(history::QueryResults* results) { | 337 void HistorySearchFunction::SearchComplete(history::QueryResults* results) { |
| 337 HistoryItemList history_item_vec; | 338 HistoryItemList history_item_vec; |
| 338 if (results && !results->empty()) { | 339 if (results && !results->empty()) { |
| 339 for (const history::URLResult* item : *results) | 340 for (const history::URLResult* item : *results) |
| 340 history_item_vec.push_back(GetHistoryItem(*item)); | 341 history_item_vec.push_back(GetHistoryItem(*item)); |
| 341 } | 342 } |
| 342 results_ = Search::Results::Create(history_item_vec); | 343 SendAsyncResponse(ArgumentList(Search::Results::Create(history_item_vec))); |
| 343 SendAsyncResponse(); | |
| 344 } | 344 } |
| 345 | 345 |
| 346 bool HistoryAddUrlFunction::RunAsync() { | 346 ExtensionFunction::ResponseAction HistoryAddUrlFunction::Run() { |
| 347 std::unique_ptr<AddUrl::Params> params(AddUrl::Params::Create(*args_)); | 347 std::unique_ptr<AddUrl::Params> params(AddUrl::Params::Create(*args_)); |
| 348 EXTENSION_FUNCTION_VALIDATE(params.get()); | 348 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 349 | 349 |
| 350 GURL url; | 350 GURL url; |
| 351 if (!ValidateUrl(params->details.url, &url)) | 351 std::string error; |
| 352 return false; | 352 if (!ValidateUrl(params->details.url, &url, &error)) |
| 353 return RespondNow(Error(error)); | |
| 353 | 354 |
| 354 history::HistoryService* hs = HistoryServiceFactory::GetForProfile( | 355 history::HistoryService* hs = HistoryServiceFactory::GetForProfile( |
| 355 GetProfile(), ServiceAccessType::EXPLICIT_ACCESS); | 356 GetProfile(), ServiceAccessType::EXPLICIT_ACCESS); |
| 356 hs->AddPage(url, base::Time::Now(), history::SOURCE_EXTENSION); | 357 hs->AddPage(url, base::Time::Now(), history::SOURCE_EXTENSION); |
| 357 | 358 |
| 358 SendResponse(true); | 359 return RespondNow(NoArguments()); |
| 359 return true; | |
| 360 } | 360 } |
| 361 | 361 |
| 362 bool HistoryDeleteUrlFunction::RunAsync() { | 362 ExtensionFunction::ResponseAction HistoryDeleteUrlFunction::Run() { |
| 363 std::unique_ptr<DeleteUrl::Params> params(DeleteUrl::Params::Create(*args_)); | 363 std::unique_ptr<DeleteUrl::Params> params(DeleteUrl::Params::Create(*args_)); |
| 364 EXTENSION_FUNCTION_VALIDATE(params.get()); | 364 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 365 | 365 |
| 366 if (!VerifyDeleteAllowed()) | 366 std::string error; |
| 367 return false; | 367 if (!VerifyDeleteAllowed(&error)) |
| 368 return RespondNow(Error(error)); | |
| 368 | 369 |
| 369 GURL url; | 370 GURL url; |
| 370 if (!ValidateUrl(params->details.url, &url)) | 371 if (!ValidateUrl(params->details.url, &url, &error)) |
| 371 return false; | 372 return RespondNow(Error(error)); |
| 372 | 373 |
| 373 history::HistoryService* hs = HistoryServiceFactory::GetForProfile( | 374 history::HistoryService* hs = HistoryServiceFactory::GetForProfile( |
| 374 GetProfile(), ServiceAccessType::EXPLICIT_ACCESS); | 375 GetProfile(), ServiceAccessType::EXPLICIT_ACCESS); |
| 375 hs->DeleteURL(url); | 376 hs->DeleteURL(url); |
| 376 | 377 |
| 377 // Also clean out from the activity log. If the activity log testing flag is | 378 // Also clean out from the activity log. If the activity log testing flag is |
| 378 // set then don't clean so testers can see what potentially malicious | 379 // set then don't clean so testers can see what potentially malicious |
| 379 // extensions have been trying to clean from their logs. | 380 // extensions have been trying to clean from their logs. |
| 380 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 381 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 381 switches::kEnableExtensionActivityLogTesting)) { | 382 switches::kEnableExtensionActivityLogTesting)) { |
| 382 ActivityLog* activity_log = ActivityLog::GetInstance(GetProfile()); | 383 ActivityLog* activity_log = ActivityLog::GetInstance(GetProfile()); |
| 383 DCHECK(activity_log); | 384 DCHECK(activity_log); |
| 384 activity_log->RemoveURL(url); | 385 activity_log->RemoveURL(url); |
| 385 } | 386 } |
| 386 | 387 |
| 387 SendResponse(true); | 388 return RespondNow(NoArguments()); |
| 388 return true; | |
| 389 } | 389 } |
| 390 | 390 |
| 391 bool HistoryDeleteRangeFunction::RunAsyncImpl() { | 391 ExtensionFunction::ResponseAction HistoryDeleteRangeFunction::Run() { |
| 392 std::unique_ptr<DeleteRange::Params> params( | 392 std::unique_ptr<DeleteRange::Params> params( |
| 393 DeleteRange::Params::Create(*args_)); | 393 DeleteRange::Params::Create(*args_)); |
| 394 EXTENSION_FUNCTION_VALIDATE(params.get()); | 394 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 395 | 395 |
| 396 if (!VerifyDeleteAllowed()) | 396 std::string error; |
| 397 return false; | 397 if (!VerifyDeleteAllowed(&error)) |
| 398 return RespondNow(Error(error)); | |
| 398 | 399 |
| 399 base::Time start_time = GetTime(params->range.start_time); | 400 base::Time start_time = GetTime(params->range.start_time); |
| 400 base::Time end_time = GetTime(params->range.end_time); | 401 base::Time end_time = GetTime(params->range.end_time); |
| 401 | 402 |
| 402 std::set<GURL> restrict_urls; | 403 std::set<GURL> restrict_urls; |
| 403 history::HistoryService* hs = HistoryServiceFactory::GetForProfile( | 404 history::HistoryService* hs = HistoryServiceFactory::GetForProfile( |
| 404 GetProfile(), ServiceAccessType::EXPLICIT_ACCESS); | 405 GetProfile(), ServiceAccessType::EXPLICIT_ACCESS); |
| 405 hs->ExpireHistoryBetween( | 406 hs->ExpireHistoryBetween( |
| 406 restrict_urls, | 407 restrict_urls, |
| 407 start_time, | 408 start_time, |
| 408 end_time, | 409 end_time, |
| 409 base::Bind(&HistoryDeleteRangeFunction::DeleteComplete, | 410 base::Bind(&HistoryDeleteRangeFunction::DeleteComplete, |
| 410 base::Unretained(this)), | 411 base::Unretained(this)), |
| 411 &task_tracker_); | 412 &task_tracker_); |
| 412 | 413 |
| 413 // Also clean from the activity log unless in testing mode. | 414 // Also clean from the activity log unless in testing mode. |
| 414 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 415 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 415 switches::kEnableExtensionActivityLogTesting)) { | 416 switches::kEnableExtensionActivityLogTesting)) { |
| 416 ActivityLog* activity_log = ActivityLog::GetInstance(GetProfile()); | 417 ActivityLog* activity_log = ActivityLog::GetInstance(GetProfile()); |
| 417 DCHECK(activity_log); | 418 DCHECK(activity_log); |
| 418 activity_log->RemoveURLs(restrict_urls); | 419 activity_log->RemoveURLs(restrict_urls); |
| 419 } | 420 } |
| 420 | 421 |
| 421 return true; | 422 AddRef(); // Balanced in SendAsyncResponse(). |
| 423 return RespondLater(); // DeleteComplete() will be called asynchronously. | |
| 422 } | 424 } |
| 423 | 425 |
| 424 void HistoryDeleteRangeFunction::DeleteComplete() { | 426 void HistoryDeleteRangeFunction::DeleteComplete() { |
| 425 SendAsyncResponse(); | 427 SendAsyncResponse(NoArguments()); |
| 426 } | 428 } |
| 427 | 429 |
| 428 bool HistoryDeleteAllFunction::RunAsyncImpl() { | 430 ExtensionFunction::ResponseAction HistoryDeleteAllFunction::Run() { |
| 429 if (!VerifyDeleteAllowed()) | 431 std::string error; |
| 430 return false; | 432 if (!VerifyDeleteAllowed(&error)) |
| 433 return RespondNow(Error(error)); | |
| 431 | 434 |
| 432 std::set<GURL> restrict_urls; | 435 std::set<GURL> restrict_urls; |
| 433 history::HistoryService* hs = HistoryServiceFactory::GetForProfile( | 436 history::HistoryService* hs = HistoryServiceFactory::GetForProfile( |
| 434 GetProfile(), ServiceAccessType::EXPLICIT_ACCESS); | 437 GetProfile(), ServiceAccessType::EXPLICIT_ACCESS); |
| 435 hs->ExpireHistoryBetween( | 438 hs->ExpireHistoryBetween( |
| 436 restrict_urls, | 439 restrict_urls, |
| 437 base::Time(), // Unbounded beginning... | 440 base::Time(), // Unbounded beginning... |
| 438 base::Time(), // ...and the end. | 441 base::Time(), // ...and the end. |
| 439 base::Bind(&HistoryDeleteAllFunction::DeleteComplete, | 442 base::Bind(&HistoryDeleteAllFunction::DeleteComplete, |
| 440 base::Unretained(this)), | 443 base::Unretained(this)), |
| 441 &task_tracker_); | 444 &task_tracker_); |
| 442 | 445 |
| 443 // Also clean from the activity log unless in testing mode. | 446 // Also clean from the activity log unless in testing mode. |
| 444 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 447 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 445 switches::kEnableExtensionActivityLogTesting)) { | 448 switches::kEnableExtensionActivityLogTesting)) { |
| 446 ActivityLog* activity_log = ActivityLog::GetInstance(GetProfile()); | 449 ActivityLog* activity_log = ActivityLog::GetInstance(GetProfile()); |
| 447 DCHECK(activity_log); | 450 DCHECK(activity_log); |
| 448 activity_log->RemoveURLs(restrict_urls); | 451 activity_log->RemoveURLs(restrict_urls); |
| 449 } | 452 } |
| 450 | 453 |
| 451 return true; | 454 AddRef(); // Balanced in SendAsyncResponse(). |
| 455 return RespondLater(); // DeleteComplete() will be called asynchronously. | |
| 452 } | 456 } |
| 453 | 457 |
| 454 void HistoryDeleteAllFunction::DeleteComplete() { | 458 void HistoryDeleteAllFunction::DeleteComplete() { |
| 455 SendAsyncResponse(); | 459 SendAsyncResponse(NoArguments()); |
| 456 } | 460 } |
| 457 | 461 |
| 458 } // namespace extensions | 462 } // namespace extensions |
| OLD | NEW |