Fixed use-after-free in LoadCallback in bookmark_storage.cc

Note: this is a reland of https://codereview.chromium.org/373153002/
after plugging a memory leak.

BookmarkStorage isn't ref counted anymore since
https://codereview.chromium.org/370323002, and the LoadCallback() task
now gets a WeakPtr to the owning BookmarkStorage. However, it gets a
raw pointer to the BookmarkLoadDetails object, which is still owned
by BookmarkStorage and may have been destroyed when the background
task runs.

This happened on iOS tests after a recent merge.

TBR=sky@chromium.org
BUG=165760

Review URL: https://codereview.chromium.org/376203002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282097 0039d316-1c4b-4281-b951-d872f2087c98
parent 412e510b
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
#include "chrome/browser/policy/profile_policy_connector.h" #include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/policy/profile_policy_connector_factory.h" #include "chrome/browser/policy/profile_policy_connector_factory.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/startup_task_runner_service.h"
#include "chrome/browser/profiles/startup_task_runner_service_factory.h"
#include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_node.h" #include "components/bookmarks/browser/bookmark_node.h"
#include "components/history/core/browser/url_database.h" #include "components/history/core/browser/url_database.h"
...@@ -171,8 +169,6 @@ bookmarks::LoadExtraCallback ChromeBookmarkClient::GetLoadExtraNodesCallback() { ...@@ -171,8 +169,6 @@ bookmarks::LoadExtraCallback ChromeBookmarkClient::GetLoadExtraNodesCallback() {
return base::Bind( return base::Bind(
&ChromeBookmarkClient::LoadExtraNodes, &ChromeBookmarkClient::LoadExtraNodes,
StartupTaskRunnerServiceFactory::GetForProfile(profile_)
->GetBookmarkTaskRunner(),
base::Passed(&managed), base::Passed(&managed),
base::Passed(managed_bookmarks_tracker_->GetInitialManagedBookmarks())); base::Passed(managed_bookmarks_tracker_->GetInitialManagedBookmarks()));
} }
...@@ -238,11 +234,9 @@ void ChromeBookmarkClient::BookmarkModelLoaded(BookmarkModel* model, ...@@ -238,11 +234,9 @@ void ChromeBookmarkClient::BookmarkModelLoaded(BookmarkModel* model,
// static // static
bookmarks::BookmarkPermanentNodeList ChromeBookmarkClient::LoadExtraNodes( bookmarks::BookmarkPermanentNodeList ChromeBookmarkClient::LoadExtraNodes(
const scoped_refptr<base::DeferredSequencedTaskRunner>& profile_io_runner,
scoped_ptr<BookmarkPermanentNode> managed_node, scoped_ptr<BookmarkPermanentNode> managed_node,
scoped_ptr<base::ListValue> initial_managed_bookmarks, scoped_ptr<base::ListValue> initial_managed_bookmarks,
int64* next_node_id) { int64* next_node_id) {
DCHECK(profile_io_runner->RunsTasksOnCurrentThread());
// Load the initial contents of the |managed_node| now, and assign it an // Load the initial contents of the |managed_node| now, and assign it an
// unused ID. // unused ID.
int64 managed_id = *next_node_id; int64 managed_id = *next_node_id;
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include "base/deferred_sequenced_task_runner.h" #include "base/deferred_sequenced_task_runner.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "components/bookmarks/browser/base_bookmark_model_observer.h" #include "components/bookmarks/browser/base_bookmark_model_observer.h"
#include "components/bookmarks/browser/bookmark_client.h" #include "components/bookmarks/browser/bookmark_client.h"
#include "components/policy/core/browser/managed_bookmarks_tracker.h" #include "components/policy/core/browser/managed_bookmarks_tracker.h"
...@@ -83,7 +82,6 @@ class ChromeBookmarkClient : public bookmarks::BookmarkClient, ...@@ -83,7 +82,6 @@ class ChromeBookmarkClient : public bookmarks::BookmarkClient,
// Helper for GetLoadExtraNodesCallback(). // Helper for GetLoadExtraNodesCallback().
static bookmarks::BookmarkPermanentNodeList LoadExtraNodes( static bookmarks::BookmarkPermanentNodeList LoadExtraNodes(
const scoped_refptr<base::DeferredSequencedTaskRunner>& profile_io_runner,
scoped_ptr<BookmarkPermanentNode> managed_node, scoped_ptr<BookmarkPermanentNode> managed_node,
scoped_ptr<base::ListValue> initial_managed_bookmarks, scoped_ptr<base::ListValue> initial_managed_bookmarks,
int64* next_node_id); int64* next_node_id);
......
...@@ -49,7 +49,7 @@ void AddBookmarksToIndex(BookmarkLoadDetails* details, ...@@ -49,7 +49,7 @@ void AddBookmarksToIndex(BookmarkLoadDetails* details,
void LoadCallback(const base::FilePath& path, void LoadCallback(const base::FilePath& path,
const base::WeakPtr<BookmarkStorage>& storage, const base::WeakPtr<BookmarkStorage>& storage,
BookmarkLoadDetails* details, scoped_ptr<BookmarkLoadDetails> details,
base::SequencedTaskRunner* task_runner) { base::SequencedTaskRunner* task_runner) {
startup_metric_utils::ScopedSlowStartupUMA startup_metric_utils::ScopedSlowStartupUMA
scoped_timer("Startup.SlowStartupBookmarksLoad"); scoped_timer("Startup.SlowStartupBookmarksLoad");
...@@ -96,17 +96,18 @@ void LoadCallback(const base::FilePath& path, ...@@ -96,17 +96,18 @@ void LoadCallback(const base::FilePath& path,
if (load_index) { if (load_index) {
TimeTicks start_time = TimeTicks::Now(); TimeTicks start_time = TimeTicks::Now();
AddBookmarksToIndex(details, details->bb_node()); AddBookmarksToIndex(details.get(), details->bb_node());
AddBookmarksToIndex(details, details->other_folder_node()); AddBookmarksToIndex(details.get(), details->other_folder_node());
AddBookmarksToIndex(details, details->mobile_folder_node()); AddBookmarksToIndex(details.get(), details->mobile_folder_node());
for (size_t i = 0; i < extra_nodes.size(); ++i) for (size_t i = 0; i < extra_nodes.size(); ++i)
AddBookmarksToIndex(details, extra_nodes[i]); AddBookmarksToIndex(details.get(), extra_nodes[i]);
UMA_HISTOGRAM_TIMES("Bookmarks.CreateBookmarkIndexTime", UMA_HISTOGRAM_TIMES("Bookmarks.CreateBookmarkIndexTime",
TimeTicks::Now() - start_time); TimeTicks::Now() - start_time);
} }
task_runner->PostTask(FROM_HERE, task_runner->PostTask(FROM_HERE,
base::Bind(&BookmarkStorage::OnLoadFinished, storage)); base::Bind(&BookmarkStorage::OnLoadFinished, storage,
base::Passed(&details)));
} }
} // namespace } // namespace
...@@ -162,14 +163,11 @@ BookmarkStorage::~BookmarkStorage() { ...@@ -162,14 +163,11 @@ BookmarkStorage::~BookmarkStorage() {
void BookmarkStorage::LoadBookmarks( void BookmarkStorage::LoadBookmarks(
scoped_ptr<BookmarkLoadDetails> details, scoped_ptr<BookmarkLoadDetails> details,
const scoped_refptr<base::SequencedTaskRunner>& task_runner) { const scoped_refptr<base::SequencedTaskRunner>& task_runner) {
DCHECK(!details_.get());
DCHECK(details);
details_ = details.Pass();
sequenced_task_runner_->PostTask(FROM_HERE, sequenced_task_runner_->PostTask(FROM_HERE,
base::Bind(&LoadCallback, base::Bind(&LoadCallback,
writer_.path(), writer_.path(),
weak_factory_.GetWeakPtr(), weak_factory_.GetWeakPtr(),
details_.get(), base::Passed(&details),
task_runner)); task_runner));
} }
...@@ -193,11 +191,11 @@ bool BookmarkStorage::SerializeData(std::string* output) { ...@@ -193,11 +191,11 @@ bool BookmarkStorage::SerializeData(std::string* output) {
return serializer.Serialize(*(value.get())); return serializer.Serialize(*(value.get()));
} }
void BookmarkStorage::OnLoadFinished() { void BookmarkStorage::OnLoadFinished(scoped_ptr<BookmarkLoadDetails> details) {
if (!model_) if (!model_)
return; return;
model_->DoneLoading(details_.Pass()); model_->DoneLoading(details.Pass());
} }
bool BookmarkStorage::SaveNow() { bool BookmarkStorage::SaveNow() {
......
...@@ -159,7 +159,7 @@ class BookmarkStorage : public base::ImportantFileWriter::DataSerializer { ...@@ -159,7 +159,7 @@ class BookmarkStorage : public base::ImportantFileWriter::DataSerializer {
void BookmarkModelDeleted(); void BookmarkModelDeleted();
// Callback from backend after loading the bookmark file. // Callback from backend after loading the bookmark file.
void OnLoadFinished(); void OnLoadFinished(scoped_ptr<BookmarkLoadDetails> details);
// ImportantFileWriter::DataSerializer implementation. // ImportantFileWriter::DataSerializer implementation.
virtual bool SerializeData(std::string* output) OVERRIDE; virtual bool SerializeData(std::string* output) OVERRIDE;
...@@ -175,9 +175,6 @@ class BookmarkStorage : public base::ImportantFileWriter::DataSerializer { ...@@ -175,9 +175,6 @@ class BookmarkStorage : public base::ImportantFileWriter::DataSerializer {
// Helper to write bookmark data safely. // Helper to write bookmark data safely.
base::ImportantFileWriter writer_; base::ImportantFileWriter writer_;
// See class description of BookmarkLoadDetails for details on this.
scoped_ptr<BookmarkLoadDetails> details_;
// Sequenced task runner where file I/O operations will be performed at. // Sequenced task runner where file I/O operations will be performed at.
scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_; scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment