Home | History | Annotate | Download | only in messaging
      1 // Copyright 2013 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/api/messaging/incognito_connectability.h"
      6 
      7 #include "base/lazy_instance.h"
      8 #include "base/logging.h"
      9 #include "base/strings/string16.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "chrome/browser/ui/simple_message_box.h"
     12 #include "content/public/browser/web_contents.h"
     13 #include "content/public/browser/web_contents_view.h"
     14 #include "extensions/common/extension.h"
     15 #include "grit/generated_resources.h"
     16 #include "ui/base/l10n/l10n_util.h"
     17 
     18 namespace extensions {
     19 
     20 namespace {
     21 IncognitoConnectability::ScopedAlertTracker::Mode g_alert_mode =
     22     IncognitoConnectability::ScopedAlertTracker::INTERACTIVE;
     23 int g_alert_count = 0;
     24 }
     25 
     26 IncognitoConnectability::ScopedAlertTracker::ScopedAlertTracker(Mode mode)
     27     : last_checked_invocation_count_(g_alert_count) {
     28   DCHECK_EQ(INTERACTIVE, g_alert_mode);
     29   DCHECK_NE(INTERACTIVE, mode);
     30   g_alert_mode = mode;
     31 }
     32 
     33 IncognitoConnectability::ScopedAlertTracker::~ScopedAlertTracker() {
     34   DCHECK_NE(INTERACTIVE, g_alert_mode);
     35   g_alert_mode = INTERACTIVE;
     36 }
     37 
     38 int IncognitoConnectability::ScopedAlertTracker::GetAndResetAlertCount() {
     39   int result = g_alert_count - last_checked_invocation_count_;
     40   last_checked_invocation_count_ = g_alert_count;
     41   return result;
     42 }
     43 
     44 IncognitoConnectability::IncognitoConnectability(Profile* profile) {
     45   CHECK(profile->IsOffTheRecord());
     46 }
     47 
     48 IncognitoConnectability::~IncognitoConnectability() {
     49 }
     50 
     51 // static
     52 IncognitoConnectability* IncognitoConnectability::Get(Profile* profile) {
     53   return ProfileKeyedAPIFactory<IncognitoConnectability>::GetForProfile(
     54       profile);
     55 }
     56 
     57 bool IncognitoConnectability::Query(const Extension* extension,
     58                                     content::WebContents* web_contents,
     59                                     const GURL& url) {
     60   GURL origin = url.GetOrigin();
     61   if (origin.is_empty())
     62     return false;
     63 
     64   if (IsInMap(extension, origin, allowed_origins_))
     65     return true;
     66   if (IsInMap(extension, origin, disallowed_origins_))
     67     return false;
     68 
     69   // We need to ask the user.
     70   ++g_alert_count;
     71   chrome::MessageBoxResult result = chrome::MESSAGE_BOX_RESULT_NO;
     72 
     73   switch (g_alert_mode) {
     74     // Production code should always be using INTERACTIVE.
     75     case ScopedAlertTracker::INTERACTIVE: {
     76       int template_id = extension->is_app() ?
     77           IDS_EXTENSION_PROMPT_APP_CONNECT_FROM_INCOGNITO :
     78           IDS_EXTENSION_PROMPT_EXTENSION_CONNECT_FROM_INCOGNITO;
     79       result = chrome::ShowMessageBox(
     80           web_contents ? web_contents->GetView()->GetTopLevelNativeWindow()
     81                        : NULL,
     82           base::string16(),  // no title
     83           l10n_util::GetStringFUTF16(template_id,
     84                                      UTF8ToUTF16(origin.spec()),
     85                                      UTF8ToUTF16(extension->name())),
     86           chrome::MESSAGE_BOX_TYPE_QUESTION);
     87       break;
     88     }
     89 
     90     // Testing code can override to always allow or deny.
     91     case ScopedAlertTracker::ALWAYS_ALLOW:
     92       result = chrome::MESSAGE_BOX_RESULT_YES;
     93       break;
     94     case ScopedAlertTracker::ALWAYS_DENY:
     95       result = chrome::MESSAGE_BOX_RESULT_NO;
     96       break;
     97   }
     98 
     99   if (result == chrome::MESSAGE_BOX_RESULT_NO) {
    100     disallowed_origins_[extension->id()].insert(origin);
    101     return false;
    102   }
    103   allowed_origins_[extension->id()].insert(origin);
    104   return true;
    105 }
    106 
    107 bool IncognitoConnectability::IsInMap(const Extension* extension,
    108                                       const GURL& origin,
    109                                       const ExtensionToOriginsMap& map) {
    110   DCHECK_EQ(origin, origin.GetOrigin());
    111   ExtensionToOriginsMap::const_iterator it = map.find(extension->id());
    112   return it != map.end() && it->second.count(origin) > 0;
    113 }
    114 
    115 static base::LazyInstance<ProfileKeyedAPIFactory<IncognitoConnectability> >
    116     g_factory = LAZY_INSTANCE_INITIALIZER;
    117 
    118 // static
    119 ProfileKeyedAPIFactory<IncognitoConnectability>*
    120 IncognitoConnectability::GetFactoryInstance() {
    121   return &g_factory.Get();
    122 }
    123 
    124 }  // namespace extensions
    125