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->get(); 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