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 "chrome/grit/generated_resources.h" 14 #include "content/public/browser/web_contents.h" 15 #include "extensions/common/extension.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