summaryrefslogtreecommitdiffstats
path: root/webkit/fileapi
diff options
context:
space:
mode:
authorkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-05 14:16:32 +0000
committerkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-05 14:16:32 +0000
commita6d281e49c9c761432832c72fdbd42685f2dded8 (patch)
tree47cc0b8b6c6c67b7f55ec6077504f62721a753a0 /webkit/fileapi
parent2702b6511ac7c84db52cbc70f4aca7bc7ca5331a (diff)
downloadchromium_src-a6d281e49c9c761432832c72fdbd42685f2dded8.zip
chromium_src-a6d281e49c9c761432832c72fdbd42685f2dded8.tar.gz
chromium_src-a6d281e49c9c761432832c72fdbd42685f2dded8.tar.bz2
2nd try: Plumbing for LocalChangeObserver
This is a bit awkward as the sync/change status is kept on IO thread while changes are recorded on FILE thread, but should work. BUG=156599 TEST=LocalFileSyncServiceTest.LocalChangeObserver\* TBR=tzik@chromium.org Original review: http://codereview.chromium.org/11365032/ Review URL: https://codereview.chromium.org/11362080 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@165934 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/fileapi')
-rw-r--r--webkit/fileapi/sandbox_mount_point_provider.cc35
-rw-r--r--webkit/fileapi/sandbox_mount_point_provider.h7
-rw-r--r--webkit/fileapi/sandbox_quota_observer.cc25
-rw-r--r--webkit/fileapi/sandbox_quota_observer.h8
-rw-r--r--webkit/fileapi/syncable/local_file_change_tracker.cc9
-rw-r--r--webkit/fileapi/syncable/local_file_change_tracker.h13
-rw-r--r--webkit/fileapi/syncable/local_file_sync_context.cc61
-rw-r--r--webkit/fileapi/syncable/local_file_sync_context.h32
-rw-r--r--webkit/fileapi/syncable/local_origin_change_observer.h28
-rw-r--r--webkit/fileapi/webkit_fileapi.gypi1
10 files changed, 195 insertions, 24 deletions
diff --git a/webkit/fileapi/sandbox_mount_point_provider.cc b/webkit/fileapi/sandbox_mount_point_provider.cc
index 040f267..1698bdc 100644
--- a/webkit/fileapi/sandbox_mount_point_provider.cc
+++ b/webkit/fileapi/sandbox_mount_point_provider.cc
@@ -339,7 +339,7 @@ SandboxMountPointProvider::SandboxMountPointProvider(
quota_observer_(new SandboxQuotaObserver(
quota_manager_proxy,
file_task_runner,
- ALLOW_THIS_IN_INITIALIZER_LIST(this))),
+ sandbox_file_util_.get())),
weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
// Set quota observers.
UpdateObserverList::Source update_observers_src;
@@ -356,8 +356,11 @@ SandboxMountPointProvider::SandboxMountPointProvider(
SandboxMountPointProvider::~SandboxMountPointProvider() {
if (!file_task_runner_->RunsTasksOnCurrentThread()) {
ObfuscatedFileUtil* sandbox_file_util = sandbox_file_util_.release();
+ SandboxQuotaObserver* quota_observer = quota_observer_.release();
if (!file_task_runner_->DeleteSoon(FROM_HERE, sandbox_file_util))
delete sandbox_file_util;
+ if (!file_task_runner_->DeleteSoon(FROM_HERE, quota_observer))
+ delete quota_observer;
}
}
@@ -649,8 +652,11 @@ int64 SandboxMountPointProvider::GetOriginUsageOnFileThread(
void SandboxMountPointProvider::InvalidateUsageCache(
const GURL& origin_url, fileapi::FileSystemType type) {
DCHECK(CanHandleType(type));
+ base::PlatformFileError error = base::PLATFORM_FILE_OK;
FilePath usage_file_path = GetUsageCachePathForOriginAndType(
- origin_url, type);
+ sandbox_file_util_.get(), origin_url, type, &error);
+ if (error != base::PLATFORM_FILE_OK)
+ return;
FileSystemUsageCache::IncrementDirty(usage_file_path);
}
@@ -729,10 +735,27 @@ SandboxMountPointProvider::CreateFileSystemOperationForSync(
}
FilePath SandboxMountPointProvider::GetUsageCachePathForOriginAndType(
- const GURL& origin_url, fileapi::FileSystemType type) const {
- FilePath base_path =
- GetBaseDirectoryForOriginAndType(origin_url, type, false);
- if (base_path.empty())
+ const GURL& origin_url,
+ FileSystemType type) const {
+ base::PlatformFileError error;
+ FilePath path = GetUsageCachePathForOriginAndType(
+ sandbox_file_util_.get(), origin_url, type, &error);
+ if (error != base::PLATFORM_FILE_OK)
+ return FilePath();
+ return path;
+}
+
+// static
+FilePath SandboxMountPointProvider::GetUsageCachePathForOriginAndType(
+ ObfuscatedFileUtil* sandbox_file_util,
+ const GURL& origin_url,
+ fileapi::FileSystemType type,
+ base::PlatformFileError* error_out) {
+ DCHECK(error_out);
+ *error_out = base::PLATFORM_FILE_OK;
+ FilePath base_path = sandbox_file_util->GetDirectoryForOriginAndType(
+ origin_url, type, false /* create */, error_out);
+ if (*error_out != base::PLATFORM_FILE_OK)
return FilePath();
return base_path.Append(FileSystemUsageCache::kUsageFileName);
}
diff --git a/webkit/fileapi/sandbox_mount_point_provider.h b/webkit/fileapi/sandbox_mount_point_provider.h
index 99819d8..98ee129 100644
--- a/webkit/fileapi/sandbox_mount_point_provider.h
+++ b/webkit/fileapi/sandbox_mount_point_provider.h
@@ -181,6 +181,13 @@ class WEBKIT_STORAGE_EXPORT SandboxMountPointProvider
const GURL& origin_url,
FileSystemType type) const;
+ // Returns a path to the usage cache file (static version).
+ static FilePath GetUsageCachePathForOriginAndType(
+ ObfuscatedFileUtil* sandbox_file_util,
+ const GURL& origin_url,
+ FileSystemType type,
+ base::PlatformFileError* error_out);
+
FilePath OldCreateFileSystemRootPath(
const GURL& origin_url, FileSystemType type);
diff --git a/webkit/fileapi/sandbox_quota_observer.cc b/webkit/fileapi/sandbox_quota_observer.cc
index 4c744ec..e733f59 100644
--- a/webkit/fileapi/sandbox_quota_observer.cc
+++ b/webkit/fileapi/sandbox_quota_observer.cc
@@ -17,10 +17,10 @@ namespace fileapi {
SandboxQuotaObserver::SandboxQuotaObserver(
quota::QuotaManagerProxy* quota_manager_proxy,
base::SequencedTaskRunner* update_notify_runner,
- SandboxMountPointProvider* sandbox_provider)
+ ObfuscatedFileUtil* sandbox_file_util)
: quota_manager_proxy_(quota_manager_proxy),
update_notify_runner_(update_notify_runner),
- sandbox_provider_(sandbox_provider) {}
+ sandbox_file_util_(sandbox_file_util) {}
SandboxQuotaObserver::~SandboxQuotaObserver() {}
@@ -28,6 +28,8 @@ void SandboxQuotaObserver::OnStartUpdate(const FileSystemURL& url) {
DCHECK(SandboxMountPointProvider::CanHandleType(url.type()));
DCHECK(update_notify_runner_->RunsTasksOnCurrentThread());
FilePath usage_file_path = GetUsageCachePath(url);
+ if (usage_file_path.empty())
+ return;
FileSystemUsageCache::IncrementDirty(usage_file_path);
}
@@ -36,8 +38,8 @@ void SandboxQuotaObserver::OnUpdate(const FileSystemURL& url,
DCHECK(SandboxMountPointProvider::CanHandleType(url.type()));
DCHECK(update_notify_runner_->RunsTasksOnCurrentThread());
FilePath usage_file_path = GetUsageCachePath(url);
- DCHECK(!usage_file_path.empty());
- // TODO(dmikurbe): Make sure that usage_file_path is available.
+ if (usage_file_path.empty())
+ return;
FileSystemUsageCache::AtomicUpdateUsageByDelta(usage_file_path, delta);
if (quota_manager_proxy_) {
quota_manager_proxy_->NotifyStorageModified(
@@ -52,6 +54,8 @@ void SandboxQuotaObserver::OnEndUpdate(const FileSystemURL& url) {
DCHECK(SandboxMountPointProvider::CanHandleType(url.type()));
DCHECK(update_notify_runner_->RunsTasksOnCurrentThread());
FilePath usage_file_path = GetUsageCachePath(url);
+ if (usage_file_path.empty())
+ return;
FileSystemUsageCache::DecrementDirty(usage_file_path);
}
@@ -66,9 +70,16 @@ void SandboxQuotaObserver::OnAccess(const FileSystemURL& url) {
}
FilePath SandboxQuotaObserver::GetUsageCachePath(const FileSystemURL& url) {
- DCHECK(sandbox_provider_);
- return sandbox_provider_->GetUsageCachePathForOriginAndType(
- url.origin(), url.type());
+ DCHECK(sandbox_file_util_);
+ base::PlatformFileError error = base::PLATFORM_FILE_OK;
+ FilePath path = SandboxMountPointProvider::GetUsageCachePathForOriginAndType(
+ sandbox_file_util_, url.origin(), url.type(), &error);
+ if (error != base::PLATFORM_FILE_OK) {
+ LOG(WARNING) << "Could not get usage cache path for: "
+ << url.DebugString();
+ return FilePath();
+ }
+ return path;
}
} // namespace fileapi
diff --git a/webkit/fileapi/sandbox_quota_observer.h b/webkit/fileapi/sandbox_quota_observer.h
index 82b239f..d2d6326 100644
--- a/webkit/fileapi/sandbox_quota_observer.h
+++ b/webkit/fileapi/sandbox_quota_observer.h
@@ -23,7 +23,7 @@ class QuotaManagerProxy;
namespace fileapi {
class FileSystemURL;
-class SandboxMountPointProvider;
+class ObfuscatedFileUtil;
class SandboxQuotaObserver
: public FileUpdateObserver,
@@ -32,7 +32,7 @@ class SandboxQuotaObserver
SandboxQuotaObserver(
quota::QuotaManagerProxy* quota_manager_proxy,
base::SequencedTaskRunner* update_notify_runner,
- SandboxMountPointProvider* sandbox_provider);
+ ObfuscatedFileUtil* sandbox_file_util);
virtual ~SandboxQuotaObserver();
// FileUpdateObserver overrides.
@@ -49,8 +49,8 @@ class SandboxQuotaObserver
scoped_refptr<quota::QuotaManagerProxy> quota_manager_proxy_;
scoped_refptr<base::SequencedTaskRunner> update_notify_runner_;
- // Not owned; provider owns this.
- SandboxMountPointProvider* sandbox_provider_;
+ // Not owned; sandbox_file_util_ should have identical lifetime with this.
+ ObfuscatedFileUtil* sandbox_file_util_;
DISALLOW_COPY_AND_ASSIGN(SandboxQuotaObserver);
};
diff --git a/webkit/fileapi/syncable/local_file_change_tracker.cc b/webkit/fileapi/syncable/local_file_change_tracker.cc
index cd896b1..fae754e 100644
--- a/webkit/fileapi/syncable/local_file_change_tracker.cc
+++ b/webkit/fileapi/syncable/local_file_change_tracker.cc
@@ -144,10 +144,12 @@ void LocalFileChangeTracker::ClearChangesForURL(const FileSystemURL& url) {
DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
// TODO(nhiroki): propagate the error code (see http://crbug.com/152127).
ClearDirtyOnDatabase(url);
+
FileChangeMap::iterator found = changes_.find(url);
DCHECK(found != changes_.end());
change_seqs_.erase(found->second.change_seq);
changes_.erase(found);
+ UpdateNumChanges();
}
SyncStatusCode LocalFileChangeTracker::Initialize(
@@ -162,6 +164,11 @@ SyncStatusCode LocalFileChangeTracker::Initialize(
return status;
}
+void LocalFileChangeTracker::UpdateNumChanges() {
+ base::AutoLock lock(num_changes_lock_);
+ num_changes_ = static_cast<int64>(change_seqs_.size());
+}
+
void LocalFileChangeTracker::GetAllChangedURLs(FileSystemURLSet* urls) {
std::vector<FileSystemURL> url_vector;
GetNextChangedURLs(&url_vector, 0);
@@ -267,10 +274,12 @@ void LocalFileChangeTracker::RecordChange(
info.change_list.Update(change);
if (info.change_list.empty()) {
changes_.erase(url);
+ UpdateNumChanges();
return;
}
info.change_seq = current_change_seq_++;
change_seqs_[info.change_seq] = url;
+ UpdateNumChanges();
}
// TrackerDB -------------------------------------------------------------------
diff --git a/webkit/fileapi/syncable/local_file_change_tracker.h b/webkit/fileapi/syncable/local_file_change_tracker.h
index 1f00605..b482dd3 100644
--- a/webkit/fileapi/syncable/local_file_change_tracker.h
+++ b/webkit/fileapi/syncable/local_file_change_tracker.h
@@ -14,6 +14,7 @@
#include "base/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/lock.h"
#include "webkit/fileapi/file_observers.h"
#include "webkit/fileapi/file_system_url.h"
#include "webkit/fileapi/syncable/file_change.h"
@@ -73,6 +74,14 @@ class WEBKIT_STORAGE_EXPORT LocalFileChangeTracker
// left after the last shutdown (if any).
SyncStatusCode Initialize(FileSystemContext* file_system_context);
+ // This method is (exceptionally) thread-safe.
+ int64 num_changes() const {
+ base::AutoLock lock(num_changes_lock_);
+ return num_changes_;
+ }
+
+ void UpdateNumChanges();
+
private:
class TrackerDB;
friend class CannedSyncableFileSystem;
@@ -120,6 +129,10 @@ class WEBKIT_STORAGE_EXPORT LocalFileChangeTracker
// well as Drive's changestamps).
int64 current_change_seq_;
+ // This can be accessed on any threads (with num_changes_lock_).
+ int64 num_changes_;
+ mutable base::Lock num_changes_lock_;
+
DISALLOW_COPY_AND_ASSIGN(LocalFileChangeTracker);
};
diff --git a/webkit/fileapi/syncable/local_file_sync_context.cc b/webkit/fileapi/syncable/local_file_sync_context.cc
index c96bcd7..fd7b99d 100644
--- a/webkit/fileapi/syncable/local_file_sync_context.cc
+++ b/webkit/fileapi/syncable/local_file_sync_context.cc
@@ -17,6 +17,7 @@
#include "webkit/fileapi/local_file_system_operation.h"
#include "webkit/fileapi/syncable/file_change.h"
#include "webkit/fileapi/syncable/local_file_change_tracker.h"
+#include "webkit/fileapi/syncable/local_origin_change_observer.h"
#include "webkit/fileapi/syncable/syncable_file_operation_runner.h"
#include "webkit/fileapi/syncable/syncable_file_system_util.h"
@@ -24,6 +25,7 @@ namespace fileapi {
namespace {
const int kMaxConcurrentSyncableOperation = 3;
+const int kNotifyChangesDurationInSec = 1;
} // namespace
LocalFileSyncContext::LocalFileSyncContext(
@@ -31,7 +33,8 @@ LocalFileSyncContext::LocalFileSyncContext(
base::SingleThreadTaskRunner* io_task_runner)
: ui_task_runner_(ui_task_runner),
io_task_runner_(io_task_runner),
- shutdown_on_ui_(false) {
+ shutdown_on_ui_(false),
+ mock_notify_changes_duration_in_sec_(-1) {
DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
}
@@ -164,6 +167,26 @@ void LocalFileSyncContext::ApplyRemoteChange(
}
}
+void LocalFileSyncContext::AddOriginChangeObserver(
+ LocalOriginChangeObserver* observer) {
+ origin_change_observers_.AddObserver(observer);
+}
+
+void LocalFileSyncContext::RemoveOriginChangeObserver(
+ LocalOriginChangeObserver* observer) {
+ origin_change_observers_.RemoveObserver(observer);
+}
+
+void LocalFileSyncContext::NotifyAvailableChangesOnIOThread() {
+ DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
+ ui_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&LocalFileSyncContext::NotifyAvailableChanges,
+ this, origins_with_pending_changes_));
+ last_notified_changes_ = base::Time::Now();
+ origins_with_pending_changes_.clear();
+}
+
base::WeakPtr<SyncableFileOperationRunner>
LocalFileSyncContext::operation_runner() const {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
@@ -179,9 +202,18 @@ LocalFileSyncStatus* LocalFileSyncContext::sync_status() const {
void LocalFileSyncContext::OnSyncEnabled(const FileSystemURL& url) {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
+ origins_with_pending_changes_.insert(url.origin());
+ if (base::Time::Now() > last_notified_changes_ + NotifyChangesDuration()) {
+ NotifyAvailableChangesOnIOThread();
+ } else if (!timer_on_io_->IsRunning()) {
+ timer_on_io_->Start(
+ FROM_HERE, NotifyChangesDuration(), this,
+ &LocalFileSyncContext::NotifyAvailableChangesOnIOThread);
+ }
if (url_syncable_callback_.is_null() ||
- sync_status()->IsWriting(url_waiting_sync_on_io_))
+ sync_status()->IsWriting(url_waiting_sync_on_io_)) {
return;
+ }
// TODO(kinuko): may want to check how many pending tasks we have.
sync_status()->StartSyncing(url_waiting_sync_on_io_);
ui_task_runner_->PostTask(FROM_HERE, url_syncable_callback_);
@@ -196,10 +228,17 @@ void LocalFileSyncContext::OnWriteEnabled(const FileSystemURL& url) {
LocalFileSyncContext::~LocalFileSyncContext() {
}
+void LocalFileSyncContext::NotifyAvailableChanges(
+ const std::set<GURL>& origins) {
+ FOR_EACH_OBSERVER(LocalOriginChangeObserver, origin_change_observers_,
+ OnChangesAvailableInOrigins(origins));
+}
+
void LocalFileSyncContext::ShutdownOnIOThread() {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
operation_runner_.reset();
sync_status_.reset();
+ timer_on_io_.reset();
}
void LocalFileSyncContext::InitializeFileSystemContextOnIOThread(
@@ -221,15 +260,17 @@ void LocalFileSyncContext::InitializeFileSystemContextOnIOThread(
base::Bind(&LocalFileSyncContext::InitializeChangeTrackerOnFileThread,
this, tracker_ptr,
make_scoped_refptr(file_system_context)),
- base::Bind(&LocalFileSyncContext::DidInitializeChangeTracker, this,
- base::Owned(tracker_ptr),
+ base::Bind(&LocalFileSyncContext::DidInitializeChangeTrackerOnIOThread,
+ this, base::Owned(tracker_ptr),
source_url, service_name,
make_scoped_refptr(file_system_context)));
return;
}
if (!operation_runner_.get()) {
- DCHECK(!sync_status_.get());
+ DCHECK(!sync_status_);
+ DCHECK(!timer_on_io_);
sync_status_.reset(new LocalFileSyncStatus);
+ timer_on_io_.reset(new base::OneShotTimer<LocalFileSyncContext>);
operation_runner_.reset(new SyncableFileOperationRunner(
kMaxConcurrentSyncableOperation,
sync_status_.get()));
@@ -250,12 +291,13 @@ SyncStatusCode LocalFileSyncContext::InitializeChangeTrackerOnFileThread(
return (*tracker_ptr)->Initialize(file_system_context);
}
-void LocalFileSyncContext::DidInitializeChangeTracker(
+void LocalFileSyncContext::DidInitializeChangeTrackerOnIOThread(
scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
const GURL& source_url,
const std::string& service_name,
FileSystemContext* file_system_context,
SyncStatusCode status) {
+ DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
DCHECK(file_system_context);
if (status != SYNC_STATUS_OK) {
DidInitialize(source_url, file_system_context, status);
@@ -358,4 +400,11 @@ void LocalFileSyncContext::DidApplyRemoteChange(
PlatformFileErrorToSyncStatusCode(file_error)));
}
+base::TimeDelta LocalFileSyncContext::NotifyChangesDuration() {
+ if (mock_notify_changes_duration_in_sec_ >= 0)
+ return base::TimeDelta::FromSeconds(mock_notify_changes_duration_in_sec_);
+ return base::TimeDelta::FromSeconds(kNotifyChangesDurationInSec);
+}
+
+
} // namespace fileapi
diff --git a/webkit/fileapi/syncable/local_file_sync_context.h b/webkit/fileapi/syncable/local_file_sync_context.h
index 9c8d397..dbcfeea 100644
--- a/webkit/fileapi/syncable/local_file_sync_context.h
+++ b/webkit/fileapi/syncable/local_file_sync_context.h
@@ -17,6 +17,8 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "base/timer.h"
#include "googleurl/src/gurl.h"
#include "webkit/fileapi/syncable/file_change.h"
#include "webkit/fileapi/syncable/local_file_sync_status.h"
@@ -33,6 +35,7 @@ namespace fileapi {
class FileChange;
class FileSystemContext;
class LocalFileChangeTracker;
+class LocalOriginChangeObserver;
class SyncableFileOperationRunner;
// This class works as a bridge between LocalFileSyncService (which is a
@@ -96,12 +99,25 @@ class WEBKIT_STORAGE_EXPORT LocalFileSyncContext
const FileSystemURL& url,
const SyncStatusCallback& callback);
+ // They must be called on UI thread.
+ void AddOriginChangeObserver(LocalOriginChangeObserver* observer);
+ void RemoveOriginChangeObserver(LocalOriginChangeObserver* observer);
+
+ // Called by internal timer on IO thread to notify changes to UI thread.
+ void NotifyAvailableChangesOnIOThread();
+
// OperationRunner is accessible only on IO thread.
base::WeakPtr<SyncableFileOperationRunner> operation_runner() const;
// SyncContext is accessible only on IO thread.
LocalFileSyncStatus* sync_status() const;
+ // For testing; override the duration to notify changes from the
+ // default value.
+ void set_mock_notify_changes_duration_in_sec(int duration) {
+ mock_notify_changes_duration_in_sec_ = duration;
+ }
+
protected:
// LocalFileSyncStatus::Observer overrides. They are called on IO thread.
virtual void OnSyncEnabled(const FileSystemURL& url) OVERRIDE;
@@ -116,6 +132,9 @@ class WEBKIT_STORAGE_EXPORT LocalFileSyncContext
void ShutdownOnIOThread();
+ // Called from NotifyAvailableChangesOnIOThread.
+ void NotifyAvailableChanges(const std::set<GURL>& origins);
+
// Helper routines for MaybeInitializeFileSystemContext.
void InitializeFileSystemContextOnIOThread(
const GURL& source_url,
@@ -124,7 +143,7 @@ class WEBKIT_STORAGE_EXPORT LocalFileSyncContext
SyncStatusCode InitializeChangeTrackerOnFileThread(
scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
FileSystemContext* file_system_context);
- void DidInitializeChangeTracker(
+ void DidInitializeChangeTrackerOnIOThread(
scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
const GURL& source_url,
const std::string& service_name,
@@ -146,6 +165,8 @@ class WEBKIT_STORAGE_EXPORT LocalFileSyncContext
const SyncStatusCallback& callback_on_ui,
base::PlatformFileError file_error);
+ base::TimeDelta NotifyChangesDuration();
+
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
@@ -173,6 +194,15 @@ class WEBKIT_STORAGE_EXPORT LocalFileSyncContext
FileSystemURL url_waiting_sync_on_io_;
base::Closure url_syncable_callback_;
+ // Used only on IO thread for available changes notifications.
+ base::Time last_notified_changes_;
+ scoped_ptr<base::OneShotTimer<LocalFileSyncContext> > timer_on_io_;
+ std::set<GURL> origins_with_pending_changes_;
+
+ ObserverList<LocalOriginChangeObserver> origin_change_observers_;
+
+ int mock_notify_changes_duration_in_sec_;
+
DISALLOW_COPY_AND_ASSIGN(LocalFileSyncContext);
};
diff --git a/webkit/fileapi/syncable/local_origin_change_observer.h b/webkit/fileapi/syncable/local_origin_change_observer.h
new file mode 100644
index 0000000..a932917
--- /dev/null
+++ b/webkit/fileapi/syncable/local_origin_change_observer.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_FILEAPI_SYNCABLE_LOCAL_ORIGIN_CHANGE_OBSERVER_H_
+#define WEBKIT_FILEAPI_SYNCABLE_LOCAL_ORIGIN_CHANGE_OBSERVER_H_
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "googleurl/src/gurl.h"
+
+namespace fileapi {
+
+class LocalOriginChangeObserver {
+ public:
+ LocalOriginChangeObserver() {}
+ ~LocalOriginChangeObserver() {}
+
+ virtual void OnChangesAvailableInOrigins(const std::set<GURL>& origins) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LocalOriginChangeObserver);
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_FILEAPI_SYNCABLE_LOCAL_ORIGIN_CHANGE_OBSERVER_H_
diff --git a/webkit/fileapi/webkit_fileapi.gypi b/webkit/fileapi/webkit_fileapi.gypi
index cb18cf6..04370e3 100644
--- a/webkit/fileapi/webkit_fileapi.gypi
+++ b/webkit/fileapi/webkit_fileapi.gypi
@@ -86,6 +86,7 @@
'../fileapi/syncable/local_file_sync_context.h',
'../fileapi/syncable/local_file_sync_status.cc',
'../fileapi/syncable/local_file_sync_status.h',
+ '../fileapi/syncable/local_origin_change_observer.h',
'../fileapi/syncable/sync_callbacks.h',
'../fileapi/syncable/sync_file_type.h',
'../fileapi/syncable/sync_status_code.cc',