Home | History | Annotate | Download | only in extensions
      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