Home | History | Annotate | Download | only in sync_file_system
      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
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.h"
      6 
      7 #include "base/lazy_instance.h"
      8 #include "chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h"
      9 #include "chrome/browser/sync_file_system/sync_event_observer.h"
     10 #include "chrome/browser/sync_file_system/sync_file_system_service.h"
     11 #include "chrome/browser/sync_file_system/sync_file_system_service_factory.h"
     12 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
     13 #include "chrome/common/extensions/api/sync_file_system.h"
     14 #include "content/public/browser/browser_context.h"
     15 #include "extensions/browser/event_router.h"
     16 #include "extensions/browser/extension_registry.h"
     17 #include "extensions/browser/extension_system_provider.h"
     18 #include "extensions/browser/extensions_browser_client.h"
     19 #include "extensions/common/extension_set.h"
     20 #include "storage/browser/fileapi/file_system_url.h"
     21 #include "storage/common/fileapi/file_system_util.h"
     22 
     23 using sync_file_system::SyncEventObserver;
     24 
     25 namespace extensions {
     26 
     27 static base::LazyInstance<
     28     BrowserContextKeyedAPIFactory<ExtensionSyncEventObserver> > g_factory =
     29     LAZY_INSTANCE_INITIALIZER;
     30 
     31 // static
     32 BrowserContextKeyedAPIFactory<ExtensionSyncEventObserver>*
     33 ExtensionSyncEventObserver::GetFactoryInstance() {
     34   return g_factory.Pointer();
     35 }
     36 
     37 ExtensionSyncEventObserver::ExtensionSyncEventObserver(
     38     content::BrowserContext* context)
     39     : browser_context_(context), sync_service_(NULL) {}
     40 
     41 void ExtensionSyncEventObserver::InitializeForService(
     42     sync_file_system::SyncFileSystemService* sync_service) {
     43   DCHECK(sync_service);
     44   if (sync_service_ != NULL) {
     45     DCHECK_EQ(sync_service_, sync_service);
     46     return;
     47   }
     48   sync_service_ = sync_service;
     49   sync_service_->AddSyncEventObserver(this);
     50 }
     51 
     52 ExtensionSyncEventObserver::~ExtensionSyncEventObserver() {}
     53 
     54 void ExtensionSyncEventObserver::Shutdown() {
     55   if (sync_service_ != NULL)
     56     sync_service_->RemoveSyncEventObserver(this);
     57 }
     58 
     59 std::string ExtensionSyncEventObserver::GetExtensionId(
     60     const GURL& app_origin) {
     61   const Extension* app = ExtensionRegistry::Get(browser_context_)
     62       ->enabled_extensions().GetAppByURL(app_origin);
     63   if (!app) {
     64     // The app is uninstalled or disabled.
     65     return std::string();
     66   }
     67   return app->id();
     68 }
     69 
     70 void ExtensionSyncEventObserver::OnSyncStateUpdated(
     71     const GURL& app_origin,
     72     sync_file_system::SyncServiceState state,
     73     const std::string& description) {
     74   // Convert state and description into SyncState Object.
     75   api::sync_file_system::ServiceInfo service_info;
     76   service_info.state = SyncServiceStateToExtensionEnum(state);
     77   service_info.description = description;
     78   scoped_ptr<base::ListValue> params(
     79       api::sync_file_system::OnServiceStatusChanged::Create(service_info));
     80 
     81   BroadcastOrDispatchEvent(
     82       app_origin,
     83       api::sync_file_system::OnServiceStatusChanged::kEventName,
     84       params.Pass());
     85 }
     86 
     87 void ExtensionSyncEventObserver::OnFileSynced(
     88     const storage::FileSystemURL& url,
     89     sync_file_system::SyncFileStatus status,
     90     sync_file_system::SyncAction action,
     91     sync_file_system::SyncDirection direction) {
     92   scoped_ptr<base::ListValue> params(new base::ListValue());
     93 
     94   // For now we always assume events come only for files (not directories).
     95   scoped_ptr<base::DictionaryValue> entry(
     96       CreateDictionaryValueForFileSystemEntry(
     97           url, sync_file_system::SYNC_FILE_TYPE_FILE));
     98   if (!entry)
     99     return;
    100   params->Append(entry.release());
    101 
    102   // Status, SyncAction and any optional notes to go here.
    103   api::sync_file_system::FileStatus status_enum =
    104       SyncFileStatusToExtensionEnum(status);
    105   api::sync_file_system::SyncAction action_enum =
    106       SyncActionToExtensionEnum(action);
    107   api::sync_file_system::SyncDirection direction_enum =
    108       SyncDirectionToExtensionEnum(direction);
    109   params->AppendString(api::sync_file_system::ToString(status_enum));
    110   params->AppendString(api::sync_file_system::ToString(action_enum));
    111   params->AppendString(api::sync_file_system::ToString(direction_enum));
    112 
    113   BroadcastOrDispatchEvent(
    114       url.origin(),
    115       api::sync_file_system::OnFileStatusChanged::kEventName,
    116       params.Pass());
    117 }
    118 
    119 void ExtensionSyncEventObserver::BroadcastOrDispatchEvent(
    120     const GURL& app_origin,
    121     const std::string& event_name,
    122     scoped_ptr<base::ListValue> values) {
    123   // Check to see whether the event should be broadcasted to all listening
    124   // extensions or sent to a specific extension ID.
    125   bool broadcast_mode = app_origin.is_empty();
    126   EventRouter* event_router = EventRouter::Get(browser_context_);
    127   DCHECK(event_router);
    128 
    129   scoped_ptr<Event> event(new Event(event_name, values.Pass()));
    130   event->restrict_to_browser_context = browser_context_;
    131 
    132   // No app_origin, broadcast to all listening extensions for this event name.
    133   if (broadcast_mode) {
    134     event_router->BroadcastEvent(event.Pass());
    135     return;
    136   }
    137 
    138   // Dispatch to single extension ID.
    139   const std::string extension_id = GetExtensionId(app_origin);
    140   if (extension_id.empty())
    141     return;
    142   event_router->DispatchEventToExtension(extension_id, event.Pass());
    143 }
    144 
    145 template <>
    146 void BrowserContextKeyedAPIFactory<
    147     ExtensionSyncEventObserver>::DeclareFactoryDependencies() {
    148   DependsOn(sync_file_system::SyncFileSystemServiceFactory::GetInstance());
    149   DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
    150 }
    151 
    152 }  // namespace extensions
    153