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