Home | History | Annotate | Download | only in extensions
      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 "chrome/browser/extensions/extension_error_controller.h"
      6 
      7 #include "chrome/browser/extensions/extension_service.h"
      8 #include "chrome/browser/extensions/pending_extension_manager.h"
      9 #include "extensions/browser/extension_prefs.h"
     10 #include "extensions/browser/extension_registry.h"
     11 #include "extensions/browser/extension_system.h"
     12 #include "extensions/common/extension_set.h"
     13 
     14 namespace extensions {
     15 
     16 namespace {
     17 
     18 ExtensionErrorController::UICreateMethod g_create_ui =
     19     ExtensionErrorUI::Create;
     20 
     21 }
     22 
     23 ExtensionErrorController::ExtensionErrorController(
     24     content::BrowserContext* context,
     25     bool is_first_run)
     26     : browser_context_(context),
     27       is_first_run_(is_first_run) {}
     28 
     29 ExtensionErrorController::~ExtensionErrorController() {}
     30 
     31 void ExtensionErrorController::ShowErrorIfNeeded() {
     32   IdentifyAlertableExtensions();
     33 
     34   // Make sure there's something to show, and that there isn't currently a
     35   // bubble displaying.
     36   if (!blacklisted_extensions_.is_empty() && !error_ui_.get()) {
     37     if (!is_first_run_) {
     38       error_ui_.reset(g_create_ui(this));
     39       if (!error_ui_->ShowErrorInBubbleView())  // Couldn't find a browser.
     40         error_ui_.reset();
     41     } else {
     42       // First run. Just acknowledge all the extensions, silently, by
     43       // shortcutting the display of the UI and going straight to the
     44       // callback for pressing the Accept button.
     45       OnAlertClosed();
     46     }
     47   }
     48 }
     49 
     50 // static
     51 void ExtensionErrorController::SetUICreateMethodForTesting(
     52     UICreateMethod method) {
     53   g_create_ui = method;
     54 }
     55 
     56 content::BrowserContext* ExtensionErrorController::GetContext() {
     57   return browser_context_;
     58 }
     59 
     60 const ExtensionSet& ExtensionErrorController::GetExternalExtensions() {
     61   return external_extensions_;
     62 }
     63 
     64 const ExtensionSet& ExtensionErrorController::GetBlacklistedExtensions() {
     65   return blacklisted_extensions_;
     66 }
     67 
     68 void ExtensionErrorController::OnAlertAccept() {
     69   error_ui_->Close();
     70 }
     71 
     72 void ExtensionErrorController::OnAlertDetails() {
     73   error_ui_->ShowExtensions();
     74 
     75   // ShowExtensions() may cause the error UI to close synchronously, e.g. if it
     76   // causes a navigation.
     77   if (error_ui_)
     78     error_ui_->Close();
     79 }
     80 
     81 void ExtensionErrorController::OnAlertClosed() {
     82   ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context_);
     83   for (ExtensionSet::const_iterator iter = blacklisted_extensions_.begin();
     84        iter != blacklisted_extensions_.end();
     85        ++iter) {
     86     prefs->AcknowledgeBlacklistedExtension((*iter)->id());
     87   }
     88 
     89   blacklisted_extensions_.Clear();
     90   error_ui_.reset();
     91 }
     92 
     93 void ExtensionErrorController::IdentifyAlertableExtensions() {
     94   ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
     95   ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context_);
     96 
     97   // This should be clear, but in case a bubble crashed somewhere along the
     98   // line, let's make sure we start fresh.
     99   blacklisted_extensions_.Clear();
    100 
    101   // Build up the lists of extensions that require acknowledgment. If this is
    102   // the first time, grandfather extensions that would have caused
    103   // notification.
    104 
    105   const ExtensionSet& blacklisted_set = registry->blacklisted_extensions();
    106   for (ExtensionSet::const_iterator iter = blacklisted_set.begin();
    107        iter != blacklisted_set.end();
    108        ++iter) {
    109     if (!prefs->IsBlacklistedExtensionAcknowledged((*iter)->id()))
    110       blacklisted_extensions_.Insert(*iter);
    111   }
    112 
    113   ExtensionSystem* system = ExtensionSystem::Get(browser_context_);
    114   ManagementPolicy* management_policy = system->management_policy();
    115   PendingExtensionManager* pending_extension_manager =
    116       system->extension_service()->pending_extension_manager();
    117   const ExtensionSet& enabled_set = registry->enabled_extensions();
    118 
    119   for (ExtensionSet::const_iterator iter = enabled_set.begin();
    120        iter != enabled_set.end();
    121        ++iter) {
    122     const Extension* extension = *iter;
    123 
    124     // Skip for extensions that have pending updates. They will be checked again
    125     // once the pending update is finished.
    126     if (pending_extension_manager->IsIdPending(extension->id()))
    127       continue;
    128 
    129     // Extensions disabled by policy. Note: this no longer includes blacklisted
    130     // extensions, though we still show the same UI.
    131     if (!management_policy->UserMayLoad(extension, NULL /* ignore error */)) {
    132       if (!prefs->IsBlacklistedExtensionAcknowledged(extension->id()))
    133         blacklisted_extensions_.Insert(extension);
    134     }
    135   }
    136 }
    137 
    138 }  // namespace extensions
    139