Home | History | Annotate | Download | only in renderer
      1 // Copyright 2014 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 "extensions/renderer/user_script_set_manager.h"
      6 
      7 #include "components/crx_file/id_util.h"
      8 #include "content/public/renderer/render_thread.h"
      9 #include "extensions/common/extension_messages.h"
     10 #include "extensions/renderer/dispatcher.h"
     11 #include "extensions/renderer/script_injection.h"
     12 #include "extensions/renderer/user_script_set.h"
     13 #include "ipc/ipc_message.h"
     14 #include "ipc/ipc_message_macros.h"
     15 #include "third_party/WebKit/public/web/WebFrame.h"
     16 
     17 namespace extensions {
     18 
     19 UserScriptSetManager::UserScriptSetManager(const ExtensionSet* extensions)
     20     : static_scripts_(extensions), extensions_(extensions) {
     21   content::RenderThread::Get()->AddObserver(this);
     22 }
     23 
     24 UserScriptSetManager::~UserScriptSetManager() {
     25 }
     26 
     27 void UserScriptSetManager::AddObserver(Observer* observer) {
     28   observers_.AddObserver(observer);
     29 }
     30 
     31 void UserScriptSetManager::RemoveObserver(Observer* observer) {
     32   observers_.RemoveObserver(observer);
     33 }
     34 
     35 scoped_ptr<ScriptInjection>
     36 UserScriptSetManager::GetInjectionForDeclarativeScript(
     37     int script_id,
     38     blink::WebFrame* web_frame,
     39     int tab_id,
     40     const GURL& url,
     41     const Extension* extension) {
     42   UserScriptSet* user_script_set =
     43       GetProgrammaticScriptsByExtension(extension->id());
     44   if (!user_script_set)
     45     return scoped_ptr<ScriptInjection>();
     46 
     47   return user_script_set->GetDeclarativeScriptInjection(
     48       script_id,
     49       web_frame,
     50       tab_id,
     51       UserScript::BROWSER_DRIVEN,
     52       url,
     53       extension);
     54 }
     55 
     56 bool UserScriptSetManager::OnControlMessageReceived(
     57     const IPC::Message& message) {
     58   bool handled = true;
     59   IPC_BEGIN_MESSAGE_MAP(UserScriptSetManager, message)
     60     IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateUserScripts, OnUpdateUserScripts)
     61     IPC_MESSAGE_UNHANDLED(handled = false)
     62   IPC_END_MESSAGE_MAP()
     63   return handled;
     64 }
     65 
     66 void UserScriptSetManager::GetAllInjections(
     67     ScopedVector<ScriptInjection>* injections,
     68     blink::WebFrame* web_frame,
     69     int tab_id,
     70     UserScript::RunLocation run_location) {
     71   static_scripts_.GetInjections(injections, web_frame, tab_id, run_location);
     72   for (UserScriptSetMap::iterator it = programmatic_scripts_.begin();
     73        it != programmatic_scripts_.end();
     74        ++it) {
     75     it->second->GetInjections(injections, web_frame, tab_id, run_location);
     76   }
     77 }
     78 
     79 void UserScriptSetManager::GetAllActiveExtensionIds(
     80     std::set<std::string>* ids) const {
     81   DCHECK(ids);
     82   static_scripts_.GetActiveExtensionIds(ids);
     83   for (UserScriptSetMap::const_iterator it = programmatic_scripts_.begin();
     84        it != programmatic_scripts_.end();
     85        ++it) {
     86     it->second->GetActiveExtensionIds(ids);
     87   }
     88 }
     89 
     90 UserScriptSet* UserScriptSetManager::GetProgrammaticScriptsByExtension(
     91     const ExtensionId& extension_id) {
     92   UserScriptSetMap::const_iterator it =
     93       programmatic_scripts_.find(extension_id);
     94   return it != programmatic_scripts_.end() ? it->second.get() : NULL;
     95 }
     96 
     97 void UserScriptSetManager::OnUpdateUserScripts(
     98     base::SharedMemoryHandle shared_memory,
     99     const ExtensionId& extension_id,
    100     const std::set<std::string>& changed_extensions) {
    101   if (!base::SharedMemory::IsHandleValid(shared_memory)) {
    102     NOTREACHED() << "Bad scripts handle";
    103     return;
    104   }
    105 
    106   for (std::set<std::string>::const_iterator iter = changed_extensions.begin();
    107        iter != changed_extensions.end();
    108        ++iter) {
    109     if (!crx_file::id_util::IdIsValid(*iter)) {
    110       NOTREACHED() << "Invalid extension id: " << *iter;
    111       return;
    112     }
    113   }
    114 
    115   UserScriptSet* scripts = NULL;
    116   if (!extension_id.empty()) {
    117     // The expectation when there is an extension that "owns" this shared
    118     // memory region is that the |changed_extensions| is either the empty list
    119     // or just the owner.
    120     CHECK(changed_extensions.size() <= 1);
    121     if (programmatic_scripts_.find(extension_id) ==
    122         programmatic_scripts_.end()) {
    123       scripts = new UserScriptSet(extensions_);
    124       programmatic_scripts_[extension_id] = make_linked_ptr(scripts);
    125     } else {
    126       scripts = programmatic_scripts_[extension_id].get();
    127     }
    128   } else {
    129     scripts = &static_scripts_;
    130   }
    131   DCHECK(scripts);
    132 
    133   // If no extensions are included in the set, that indicates that all
    134   // extensions were updated. Add them all to the set so that observers and
    135   // individual UserScriptSets don't need to know this detail.
    136   const std::set<std::string>* effective_extensions = &changed_extensions;
    137   std::set<std::string> all_extensions;
    138   if (changed_extensions.empty()) {
    139     // The meaning of "all extensions" varies, depending on whether some
    140     // extension "owns" this shared memory region.
    141     // No owner => all known extensions.
    142     // Owner    => just the owner extension.
    143     if (extension_id.empty())
    144       all_extensions = extensions_->GetIDs();
    145     else
    146       all_extensions.insert(extension_id);
    147     effective_extensions = &all_extensions;
    148   }
    149 
    150   if (scripts->UpdateUserScripts(shared_memory, *effective_extensions)) {
    151     FOR_EACH_OBSERVER(
    152         Observer,
    153         observers_,
    154         OnUserScriptsUpdated(*effective_extensions, scripts->scripts()));
    155   }
    156 }
    157 
    158 }  // namespace extensions
    159