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/profiles/profile.h"
     12 #include "chrome/browser/ui/simple_message_box.h"
     13 #include "content/public/browser/web_contents.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(
     45     content::BrowserContext* context) {
     46   CHECK(context->IsOffTheRecord());
     47 }
     48 
     49 IncognitoConnectability::~IncognitoConnectability() {
     50 }
     51 
     52 // static
     53 IncognitoConnectability* IncognitoConnectability::Get(
     54     content::BrowserContext* context) {
     55   return BrowserContextKeyedAPIFactory<IncognitoConnectability>::Get(context);
     56 }
     57 
     58 bool IncognitoConnectability::Query(const Extension* extension,
     59                                     content::WebContents* web_contents,
     60                                     const GURL& url) {
     61   GURL origin = url.GetOrigin();
     62   if (origin.is_empty())
     63     return false;
     64 
     65   if (IsInMap(extension, origin, allowed_origins_))
     66     return true;
     67   if (IsInMap(extension, origin, disallowed_origins_))
     68     return false;
     69 
     70   // We need to ask the user.
     71   ++g_alert_count;
     72   chrome::MessageBoxResult result = chrome::MESSAGE_BOX_RESULT_NO;
     73 
     74   switch (g_alert_mode) {
     75     // Production code should always be using INTERACTIVE.
     76     case ScopedAlertTracker::INTERACTIVE: {
     77       int template_id = extension->is_app() ?
     78           IDS_EXTENSION_PROMPT_APP_CONNECT_FROM_INCOGNITO :
     79           IDS_EXTENSION_PROMPT_EXTENSION_CONNECT_FROM_INCOGNITO;
     80       result = chrome::ShowMessageBox(
     81           web_contents ? web_contents->GetTopLevelNativeWindow() : NULL,
     82           base::string16(),  // no title
     83           l10n_util::GetStringFUTF16(template_id,
     84                                      base::UTF8ToUTF16(origin.spec()),
     85                                      base::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<
    116     BrowserContextKeyedAPIFactory<IncognitoConnectability> > g_factory =
    117     LAZY_INSTANCE_INITIALIZER;
    118 
    119 // static
    120 BrowserContextKeyedAPIFactory<IncognitoConnectability>*
    121 IncognitoConnectability::GetFactoryInstance() {
    122   return g_factory.Pointer();
    123 }
    124 
    125 }  // namespace extensions
    126