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/navigation_observer.h" 6 7#include "chrome/browser/extensions/extension_install_ui.h" 8#include "chrome/browser/extensions/extension_service.h" 9#include "chrome/browser/profiles/profile.h" 10#include "content/public/browser/navigation_controller.h" 11#include "content/public/browser/navigation_entry.h" 12#include "content/public/browser/notification_service.h" 13#include "content/public/browser/notification_types.h" 14#include "extensions/browser/extension_prefs.h" 15#include "extensions/browser/extension_registry.h" 16#include "extensions/browser/extension_system.h" 17 18using content::NavigationController; 19using content::NavigationEntry; 20 21namespace extensions { 22 23NavigationObserver::NavigationObserver(Profile* profile) : profile_(profile) { 24 RegisterForNotifications(); 25} 26 27NavigationObserver::~NavigationObserver() {} 28 29void NavigationObserver::Observe(int type, 30 const content::NotificationSource& source, 31 const content::NotificationDetails& details) { 32 if (type != content::NOTIFICATION_NAV_ENTRY_COMMITTED) { 33 NOTREACHED(); 34 return; 35 } 36 37 NavigationController* controller = 38 content::Source<NavigationController>(source).ptr(); 39 if (!profile_->IsSameProfile( 40 Profile::FromBrowserContext(controller->GetBrowserContext()))) 41 return; 42 43 PromptToEnableExtensionIfNecessary(controller); 44} 45 46void NavigationObserver::RegisterForNotifications() { 47 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 48 content::NotificationService::AllSources()); 49} 50 51void NavigationObserver::PromptToEnableExtensionIfNecessary( 52 NavigationController* nav_controller) { 53 // Bail out if we're already running a prompt. 54 if (!in_progress_prompt_extension_id_.empty()) 55 return; 56 57 NavigationEntry* nav_entry = nav_controller->GetVisibleEntry(); 58 if (!nav_entry) 59 return; 60 61 ExtensionRegistry* registry = extensions::ExtensionRegistry::Get(profile_); 62 const Extension* extension = 63 registry->disabled_extensions().GetExtensionOrAppByURL( 64 nav_entry->GetURL()); 65 if (!extension) 66 return; 67 68 // Try not to repeatedly prompt the user about the same extension. 69 if (prompted_extensions_.find(extension->id()) != prompted_extensions_.end()) 70 return; 71 prompted_extensions_.insert(extension->id()); 72 73 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile_); 74 if (extension_prefs->DidExtensionEscalatePermissions(extension->id())) { 75 // Keep track of the extension id and nav controller we're prompting for. 76 // These must be reset in InstallUIProceed and InstallUIAbort. 77 in_progress_prompt_extension_id_ = extension->id(); 78 in_progress_prompt_navigation_controller_ = nav_controller; 79 80 extension_install_prompt_.reset( 81 new ExtensionInstallPrompt(nav_controller->GetWebContents())); 82 extension_install_prompt_->ConfirmReEnable(this, extension); 83 } 84} 85 86void NavigationObserver::InstallUIProceed() { 87 ExtensionService* extension_service = 88 extensions::ExtensionSystem::Get(profile_)->extension_service(); 89 const Extension* extension = extension_service->GetExtensionById( 90 in_progress_prompt_extension_id_, true); 91 NavigationController* nav_controller = 92 in_progress_prompt_navigation_controller_; 93 CHECK(extension); 94 CHECK(nav_controller); 95 96 in_progress_prompt_extension_id_ = ""; 97 in_progress_prompt_navigation_controller_ = NULL; 98 extension_install_prompt_.reset(); 99 100 // Grant permissions, re-enable the extension, and then reload the tab. 101 extension_service->GrantPermissionsAndEnableExtension(extension); 102 nav_controller->Reload(true); 103} 104 105void NavigationObserver::InstallUIAbort(bool user_initiated) { 106 ExtensionService* extension_service = 107 extensions::ExtensionSystem::Get(profile_)->extension_service(); 108 const Extension* extension = extension_service->GetExtensionById( 109 in_progress_prompt_extension_id_, true); 110 111 in_progress_prompt_extension_id_ = ""; 112 in_progress_prompt_navigation_controller_ = NULL; 113 extension_install_prompt_.reset(); 114 115 std::string histogram_name = user_initiated 116 ? "Extensions.Permissions_ReEnableCancel2" 117 : "Extensions.Permissions_ReEnableAbort2"; 118 ExtensionService::RecordPermissionMessagesHistogram( 119 extension, histogram_name.c_str()); 120} 121 122} // namespace extensions 123