12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/lazy_instance.h" 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/sync_event_observer.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/sync_file_system_service.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/sync_file_system/sync_file_system_service_factory.h" 122385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/syncable_file_system_util.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/api/sync_file_system.h" 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/browser/browser_context.h" 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h" 16a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "extensions/browser/extension_registry.h" 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/extension_system_provider.h" 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/extensions_browser_client.h" 19a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "extensions/common/extension_set.h" 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_url.h" 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/fileapi/file_system_util.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using sync_file_system::SyncEventObserver; 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions { 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static base::LazyInstance< 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BrowserContextKeyedAPIFactory<ExtensionSyncEventObserver> > g_factory = 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LAZY_INSTANCE_INITIALIZER; 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<ExtensionSyncEventObserver>* 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ExtensionSyncEventObserver::GetFactoryInstance() { 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return g_factory.Pointer(); 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ExtensionSyncEventObserver::ExtensionSyncEventObserver( 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) content::BrowserContext* context) 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : browser_context_(context), sync_service_(NULL) {} 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionSyncEventObserver::InitializeForService( 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) sync_file_system::SyncFileSystemService* sync_service) { 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(sync_service); 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (sync_service_ != NULL) { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(sync_service_, sync_service); 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_service_ = sync_service; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_service_->AddSyncEventObserver(this); 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ExtensionSyncEventObserver::~ExtensionSyncEventObserver() {} 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionSyncEventObserver::Shutdown() { 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (sync_service_ != NULL) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_service_->RemoveSyncEventObserver(this); 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string ExtensionSyncEventObserver::GetExtensionId( 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& app_origin) { 61a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const Extension* app = ExtensionRegistry::Get(browser_context_) 62a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ->enabled_extensions().GetAppByURL(app_origin); 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!app) { 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The app is uninstalled or disabled. 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return std::string(); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return app->id(); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionSyncEventObserver::OnSyncStateUpdated( 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& app_origin, 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sync_file_system::SyncServiceState state, 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& description) { 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Convert state and description into SyncState Object. 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) api::sync_file_system::ServiceInfo service_info; 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) service_info.state = SyncServiceStateToExtensionEnum(state); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) service_info.description = description; 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::ListValue> params( 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) api::sync_file_system::OnServiceStatusChanged::Create(service_info)); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) BroadcastOrDispatchEvent( 823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) app_origin, 833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) api::sync_file_system::OnServiceStatusChanged::kEventName, 843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) params.Pass()); 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionSyncEventObserver::OnFileSynced( 8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const storage::FileSystemURL& url, 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_file_system::SyncFileStatus status, 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_file_system::SyncAction action, 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_file_system::SyncDirection direction) { 92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<base::ListValue> params(new base::ListValue()); 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // For now we always assume events come only for files (not directories). 95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) scoped_ptr<base::DictionaryValue> entry( 96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CreateDictionaryValueForFileSystemEntry( 97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) url, sync_file_system::SYNC_FILE_TYPE_FILE)); 98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!entry) 99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) params->Append(entry.release()); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Status, SyncAction and any optional notes to go here. 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) api::sync_file_system::FileStatus status_enum = 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncFileStatusToExtensionEnum(status); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) api::sync_file_system::SyncAction action_enum = 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncActionToExtensionEnum(action); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) api::sync_file_system::SyncDirection direction_enum = 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncDirectionToExtensionEnum(direction); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params->AppendString(api::sync_file_system::ToString(status_enum)); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params->AppendString(api::sync_file_system::ToString(action_enum)); 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params->AppendString(api::sync_file_system::ToString(direction_enum)); 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) BroadcastOrDispatchEvent( 1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) url.origin(), 1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) api::sync_file_system::OnFileStatusChanged::kEventName, 1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) params.Pass()); 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionSyncEventObserver::BroadcastOrDispatchEvent( 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& app_origin, 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& event_name, 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::ListValue> values) { 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check to see whether the event should be broadcasted to all listening 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // extensions or sent to a specific extension ID. 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool broadcast_mode = app_origin.is_empty(); 1260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EventRouter* event_router = EventRouter::Get(browser_context_); 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(event_router); 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<Event> event(new Event(event_name, values.Pass())); 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) event->restrict_to_browser_context = browser_context_; 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // No app_origin, broadcast to all listening extensions for this event name. 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (broadcast_mode) { 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_router->BroadcastEvent(event.Pass()); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Dispatch to single extension ID. 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string extension_id = GetExtensionId(app_origin); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (extension_id.empty()) 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_router->DispatchEventToExtension(extension_id, event.Pass()); 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)template <> 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BrowserContextKeyedAPIFactory< 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ExtensionSyncEventObserver>::DeclareFactoryDependencies() { 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DependsOn(sync_file_system::SyncFileSystemServiceFactory::GetInstance()); 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace extensions 153