summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions
diff options
context:
space:
mode:
authormpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-25 22:10:50 +0000
committermpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-25 22:10:50 +0000
commitdb7331aecb1f0c01aecf4cd4627d08a8d5b08bc2 (patch)
tree5a33fc21cb1628462f9e365add27aeaf058d60fc /chrome/browser/extensions
parentf56abff188b90b7f2d67a094930d7d9407df507d (diff)
downloadchromium_src-db7331aecb1f0c01aecf4cd4627d08a8d5b08bc2.zip
chromium_src-db7331aecb1f0c01aecf4cd4627d08a8d5b08bc2.tar.gz
chromium_src-db7331aecb1f0c01aecf4cd4627d08a8d5b08bc2.tar.bz2
Allow users to enable extensions in incognito. Requires
--enable-experimental-extension-apis . The UI needs work. Tab and window events are hooked up so that they work with incognito tabs/windows when enabled. BUG=32365 BUG=36292 Review URL: http://codereview.chromium.org/657041 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@40057 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions')
-rw-r--r--chrome/browser/extensions/execute_code_in_tab_function.cc10
-rw-r--r--chrome/browser/extensions/extension_accessibility_api.cc4
-rw-r--r--chrome/browser/extensions/extension_bookmark_manager_api.cc4
-rw-r--r--chrome/browser/extensions/extension_bookmarks_module.cc4
-rw-r--r--chrome/browser/extensions/extension_browser_event_router.cc8
-rw-r--r--chrome/browser/extensions/extension_browsertest.cc16
-rw-r--r--chrome/browser/extensions/extension_browsertest.h4
-rw-r--r--chrome/browser/extensions/extension_devtools_bridge.cc9
-rw-r--r--chrome/browser/extensions/extension_dom_ui.cc16
-rw-r--r--chrome/browser/extensions/extension_dom_ui.h3
-rw-r--r--chrome/browser/extensions/extension_function.h10
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc14
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.h9
-rw-r--r--chrome/browser/extensions/extension_history_api.cc4
-rw-r--r--chrome/browser/extensions/extension_host.cc33
-rw-r--r--chrome/browser/extensions/extension_host.h3
-rwxr-xr-xchrome/browser/extensions/extension_incognito_apitest.cc (renamed from chrome/browser/extensions/incognito_noscript_apitest.cc)80
-rw-r--r--chrome/browser/extensions/extension_message_service.cc11
-rw-r--r--chrome/browser/extensions/extension_message_service.h3
-rw-r--r--chrome/browser/extensions/extension_page_actions_module.cc6
-rw-r--r--chrome/browser/extensions/extension_popup_api.cc5
-rw-r--r--chrome/browser/extensions/extension_process_manager.cc13
-rw-r--r--chrome/browser/extensions/extension_processes_api.cc4
-rw-r--r--chrome/browser/extensions/extension_protocols.cc14
-rw-r--r--chrome/browser/extensions/extension_tabs_module.cc97
-rw-r--r--chrome/browser/extensions/extension_tabs_module.h3
-rw-r--r--chrome/browser/extensions/extension_tabs_module_constants.cc1
-rw-r--r--chrome/browser/extensions/extension_tabs_module_constants.h1
-rw-r--r--chrome/browser/extensions/extension_test_api.cc11
-rw-r--r--chrome/browser/extensions/extension_test_api.h6
-rw-r--r--chrome/browser/extensions/extension_toolstrip_api.cc6
-rw-r--r--chrome/browser/extensions/extension_ui_unittest.cc4
-rw-r--r--chrome/browser/extensions/extension_uitest.cc10
-rw-r--r--chrome/browser/extensions/extensions_service.cc18
-rw-r--r--chrome/browser/extensions/extensions_service.h5
-rw-r--r--chrome/browser/extensions/extensions_ui.cc34
-rw-r--r--chrome/browser/extensions/extensions_ui.h9
-rw-r--r--chrome/browser/extensions/user_script_master.cc29
-rw-r--r--chrome/browser/extensions/user_script_master.h5
39 files changed, 385 insertions, 141 deletions
diff --git a/chrome/browser/extensions/execute_code_in_tab_function.cc b/chrome/browser/extensions/execute_code_in_tab_function.cc
index da16d80..27ccf3f 100644
--- a/chrome/browser/extensions/execute_code_in_tab_function.cc
+++ b/chrome/browser/extensions/execute_code_in_tab_function.cc
@@ -48,7 +48,7 @@ bool ExecuteCodeInTabFunction::RunImpl() {
Value* tab_value = NULL;
EXTENSION_FUNCTION_VALIDATE(args->Get(0, &tab_value));
if (tab_value->IsType(Value::TYPE_NULL)) {
- browser = dispatcher()->GetBrowser();
+ browser = GetBrowser();
if (!browser) {
error_ = keys::kNoCurrentWindowError;
return false;
@@ -57,8 +57,9 @@ bool ExecuteCodeInTabFunction::RunImpl() {
return false;
} else {
EXTENSION_FUNCTION_VALIDATE(tab_value->GetAsInteger(&execute_tab_id_));
- if (!ExtensionTabUtil::GetTabById(execute_tab_id_, profile(), &browser,
- NULL, &contents, NULL)) {
+ if (!ExtensionTabUtil::GetTabById(execute_tab_id_, profile(),
+ include_incognito(),
+ &browser, NULL, &contents, NULL)) {
return false;
}
}
@@ -127,7 +128,8 @@ void ExecuteCodeInTabFunction::DidLoadFile(bool success,
bool ExecuteCodeInTabFunction::Execute(const std::string& code_string) {
TabContents* contents = NULL;
Browser* browser = NULL;
- if (!ExtensionTabUtil::GetTabById(execute_tab_id_, profile(), &browser, NULL,
+ if (!ExtensionTabUtil::GetTabById(execute_tab_id_, profile(),
+ include_incognito(), &browser, NULL,
&contents, NULL) && contents && browser) {
SendResponse(false);
return false;
diff --git a/chrome/browser/extensions/extension_accessibility_api.cc b/chrome/browser/extensions/extension_accessibility_api.cc
index 2ea3775..38745a7 100644
--- a/chrome/browser/extensions/extension_accessibility_api.cc
+++ b/chrome/browser/extensions/extension_accessibility_api.cc
@@ -157,8 +157,8 @@ void ExtensionAccessibilityEventRouter::DispatchEvent(
const char* event_name,
const std::string& json_args) {
if (enabled_ && profile && profile->GetExtensionMessageService()) {
- profile->GetExtensionMessageService()->
- DispatchEventToRenderers(event_name, json_args);
+ profile->GetExtensionMessageService()->DispatchEventToRenderers(
+ event_name, json_args, profile->IsOffTheRecord());
}
}
diff --git a/chrome/browser/extensions/extension_bookmark_manager_api.cc b/chrome/browser/extensions/extension_bookmark_manager_api.cc
index 81848f3..a67b716 100644
--- a/chrome/browser/extensions/extension_bookmark_manager_api.cc
+++ b/chrome/browser/extensions/extension_bookmark_manager_api.cc
@@ -170,8 +170,8 @@ void ExtensionBookmarkManagerEventRouter::DispatchEvent(const char* event_name,
std::string json_args;
base::JSONWriter::Write(args, false, &json_args);
- profile_->GetExtensionMessageService()->
- DispatchEventToRenderers(event_name, json_args);
+ profile_->GetExtensionMessageService()->DispatchEventToRenderers(
+ event_name, json_args, profile_->IsOffTheRecord());
}
void ExtensionBookmarkManagerEventRouter::DispatchDragEvent(
diff --git a/chrome/browser/extensions/extension_bookmarks_module.cc b/chrome/browser/extensions/extension_bookmarks_module.cc
index 993cb05..d561e2a 100644
--- a/chrome/browser/extensions/extension_bookmarks_module.cc
+++ b/chrome/browser/extensions/extension_bookmarks_module.cc
@@ -170,8 +170,8 @@ void ExtensionBookmarkEventRouter::DispatchEvent(Profile *profile,
const char* event_name,
const std::string json_args) {
if (profile->GetExtensionMessageService()) {
- profile->GetExtensionMessageService()->
- DispatchEventToRenderers(event_name, json_args);
+ profile->GetExtensionMessageService()->DispatchEventToRenderers(
+ event_name, json_args, profile->IsOffTheRecord());
}
}
diff --git a/chrome/browser/extensions/extension_browser_event_router.cc b/chrome/browser/extensions/extension_browser_event_router.cc
index 388863a..9b379bc 100644
--- a/chrome/browser/extensions/extension_browser_event_router.cc
+++ b/chrome/browser/extensions/extension_browser_event_router.cc
@@ -88,8 +88,8 @@ static void DispatchEvent(Profile* profile,
const char* event_name,
const std::string json_args) {
if (profile->GetExtensionMessageService()) {
- profile->GetExtensionMessageService()->
- DispatchEventToRenderers(event_name, json_args);
+ profile->GetExtensionMessageService()->DispatchEventToRenderers(
+ event_name, json_args, profile->IsOffTheRecord());
}
}
@@ -437,8 +437,8 @@ void ExtensionBrowserEventRouter::PageActionExecuted(
DispatchOldPageActionEvent(profile, extension_id, page_action_id, tab_id, url,
button);
TabContents* tab_contents = NULL;
- if (!ExtensionTabUtil::GetTabById(tab_id, profile, NULL, NULL, &tab_contents,
- NULL)) {
+ if (!ExtensionTabUtil::GetTabById(tab_id, profile, profile->IsOffTheRecord(),
+ NULL, NULL, &tab_contents, NULL)) {
return;
}
std::string event_name = std::string("pageAction/") + extension_id;
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc
index 9b4ddd8..d96d6dc 100644
--- a/chrome/browser/extensions/extension_browsertest.cc
+++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -51,7 +51,8 @@ void ExtensionBrowserTest::SetUpCommandLine(CommandLine* command_line) {
command_line->AppendSwitch(switches::kEnableExtensionToolstrips);
}
-bool ExtensionBrowserTest::LoadExtension(const FilePath& path) {
+bool ExtensionBrowserTest::LoadExtensionImpl(const FilePath& path,
+ bool incognito_enabled) {
ExtensionsService* service = browser()->profile()->GetExtensionsService();
size_t num_before = service->extensions()->size();
{
@@ -67,9 +68,22 @@ bool ExtensionBrowserTest::LoadExtension(const FilePath& path) {
if (num_after != (num_before + 1))
return false;
+ if (incognito_enabled) {
+ Extension* extension = service->extensions()->at(num_after - 1);
+ service->SetIsIncognitoEnabled(extension->id(), true);
+ }
+
return WaitForExtensionHostsToLoad();
}
+bool ExtensionBrowserTest::LoadExtension(const FilePath& path) {
+ return LoadExtensionImpl(path, false);
+}
+
+bool ExtensionBrowserTest::LoadExtensionIncognito(const FilePath& path) {
+ return LoadExtensionImpl(path, true);
+}
+
// This class is used to simulate an installation abort by the user.
class MockAbortExtensionInstallUI : public ExtensionInstallUI {
public:
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h
index 263f582..8a34903 100644
--- a/chrome/browser/extensions/extension_browsertest.h
+++ b/chrome/browser/extensions/extension_browsertest.h
@@ -25,6 +25,9 @@ class ExtensionBrowserTest
virtual void SetUpCommandLine(CommandLine* command_line);
bool LoadExtension(const FilePath& path);
+ // Same as above, but enables the extension in incognito mode first.
+ bool LoadExtensionIncognito(const FilePath& path);
+
// |expected_change| indicates how many extensions should be installed (or
// disabled, if negative).
// 1 means you expect a new install, 0 means you expect an upgrade, -1 means
@@ -93,6 +96,7 @@ class ExtensionBrowserTest
bool InstallOrUpdateExtension(const std::string& id, const FilePath& path,
bool should_cancel,
int expected_change);
+ bool LoadExtensionImpl(const FilePath& path, bool incognito_enabled);
bool WaitForExtensionHostsToLoad();
diff --git a/chrome/browser/extensions/extension_devtools_bridge.cc b/chrome/browser/extensions/extension_devtools_bridge.cc
index c9a5f50..a6399d8 100644
--- a/chrome/browser/extensions/extension_devtools_bridge.cc
+++ b/chrome/browser/extensions/extension_devtools_bridge.cc
@@ -36,7 +36,8 @@ bool ExtensionDevToolsBridge::RegisterAsDevToolsClientHost() {
TabStripModel* tab_strip;
TabContents* contents;
int tab_index;
- if (ExtensionTabUtil::GetTabById(tab_id_, profile_, &browser, &tab_strip,
+ if (ExtensionTabUtil::GetTabById(tab_id_, profile_, true,
+ &browser, &tab_strip,
&contents, &tab_index)) {
DevToolsManager* devtools_manager = DevToolsManager::GetInstance();
devtools_manager->RegisterDevToolsClientHostFor(
@@ -63,8 +64,8 @@ void ExtensionDevToolsBridge::InspectedTabClosing() {
// TODO(knorton): Remove this event in favor of the standard tabs.onRemoved
// event in extensions.
std::string json("[{}]");
- profile_->GetExtensionMessageService()->
- DispatchEventToRenderers(on_tab_close_event_name_, json);
+ profile_->GetExtensionMessageService()->DispatchEventToRenderers(
+ on_tab_close_event_name_, json, profile_->IsOffTheRecord());
// This may result in this object being destroyed.
extension_devtools_manager_->BridgeClosingForTab(tab_id_);
@@ -87,7 +88,7 @@ void ExtensionDevToolsBridge::OnRpcMessage(const DevToolsMessageData& data) {
&& data.method_name == kApuPageEventMessageName) {
std::string json = StringPrintf("[%s]", data.arguments[0].c_str());
profile_->GetExtensionMessageService()->DispatchEventToRenderers(
- on_page_event_name_, json);
+ on_page_event_name_, json, profile_->IsOffTheRecord());
}
}
diff --git a/chrome/browser/extensions/extension_dom_ui.cc b/chrome/browser/extensions/extension_dom_ui.cc
index de2d13b..b39b15b 100644
--- a/chrome/browser/extensions/extension_dom_ui.cc
+++ b/chrome/browser/extensions/extension_dom_ui.cc
@@ -76,11 +76,19 @@ void ExtensionDOMUI::ProcessDOMUIMessage(const std::string& message,
has_callback);
}
-Browser* ExtensionDOMUI::GetBrowser() const {
+Browser* ExtensionDOMUI::GetBrowser(bool include_incognito) const {
+ Browser* browser = NULL;
TabContentsDelegate* tab_contents_delegate = tab_contents()->delegate();
- if (tab_contents_delegate)
- return tab_contents_delegate->GetBrowser();
- return NULL;
+ if (tab_contents_delegate) {
+ browser = tab_contents_delegate->GetBrowser();
+ if (browser && browser->profile()->IsOffTheRecord() && !include_incognito) {
+ // Fall back to the toplevel regular browser if we don't want to include
+ // incognito browsers.
+ browser = BrowserList::GetLastActiveWithProfile(
+ browser->profile()->GetOriginalProfile());
+ }
+ }
+ return browser;
}
Profile* ExtensionDOMUI::GetProfile() {
diff --git a/chrome/browser/extensions/extension_dom_ui.h b/chrome/browser/extensions/extension_dom_ui.h
index 59a89a8..9d85ccb 100644
--- a/chrome/browser/extensions/extension_dom_ui.h
+++ b/chrome/browser/extensions/extension_dom_ui.h
@@ -41,11 +41,12 @@ class ExtensionDOMUI
bool has_callback);
// ExtensionFunctionDispatcher::Delegate
- virtual Browser* GetBrowser() const;
+ virtual Browser* GetBrowser(bool include_incognito) const;
virtual ExtensionDOMUI* GetExtensionDOMUI() { return this; }
virtual gfx::NativeWindow GetFrameNativeWindow();
// ExtensionPopupHost::Delegate
+ virtual Browser* GetBrowser() const { return GetBrowser(true); }
virtual RenderViewHost* GetRenderViewHost();
virtual Profile* GetProfile();
virtual gfx::NativeView GetNativeViewOfHost();
diff --git a/chrome/browser/extensions/extension_function.h b/chrome/browser/extensions/extension_function.h
index 6db6443..06f69ab 100644
--- a/chrome/browser/extensions/extension_function.h
+++ b/chrome/browser/extensions/extension_function.h
@@ -68,6 +68,9 @@ class ExtensionFunction : public base::RefCounted<ExtensionFunction> {
void set_has_callback(bool has_callback) { has_callback_ = has_callback; }
bool has_callback() { return has_callback_; }
+ void set_include_incognito(bool include) { include_incognito_ = include; }
+ bool include_incognito() { return include_incognito_; }
+
// Execute the API. Clients should call set_raw_args() and
// set_request_id() before calling this method. Derived classes should be
// ready to return raw_result() and error() before returning from this
@@ -88,6 +91,10 @@ class ExtensionFunction : public base::RefCounted<ExtensionFunction> {
return NULL;
}
+ Browser* GetBrowser() {
+ return dispatcher()->GetBrowser(include_incognito_);
+ }
+
// The peer to the dispatcher that will service this extension function call.
scoped_refptr<ExtensionFunctionDispatcher::Peer> peer_;
@@ -101,6 +108,9 @@ class ExtensionFunction : public base::RefCounted<ExtensionFunction> {
// of this call.
bool has_callback_;
+ // True if this callback should include information from incognito contexts.
+ bool include_incognito_;
+
DISALLOW_COPY_AND_ASSIGN(ExtensionFunction);
};
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index 69e4d54..35b73a5 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -174,6 +174,7 @@ void FactoryRegistry::ResetFunctions() {
RegisterFunction<ExtensionTestFailFunction>();
RegisterFunction<ExtensionTestLogFunction>();
RegisterFunction<ExtensionTestQuotaResetFunction>();
+ RegisterFunction<ExtensionTestCreateIncognitoTabFunction>();
// Accessibility.
RegisterFunction<GetFocusedControlFunction>();
@@ -212,7 +213,7 @@ ExtensionFunction* FactoryRegistry::NewFunction(const std::string& name) {
gfx::NativeWindow ExtensionFunctionDispatcher::Delegate::
GetFrameNativeWindow() {
- Browser* browser = GetBrowser();
+ Browser* browser = GetBrowser(true);
// If a browser is bound to this dispatcher, then return the widget hosting
// the window. Extensions hosted in ExternalTabContainer objects may not
// have a running browser instance.
@@ -266,6 +267,9 @@ ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(
epm->RegisterExtensionProcess(extension_id(),
render_view_host->process()->id());
+ bool incognito_enabled =
+ profile()->GetExtensionsService()->IsIncognitoEnabled(extension->id());
+
// Update the extension permissions. Doing this each time we create an EFD
// ensures that new processes are informed of permissions for newly installed
// extensions.
@@ -273,6 +277,8 @@ ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(
extension->id(), extension->api_permissions()));
render_view_host->Send(new ViewMsg_Extension_SetHostPermissions(
extension->url(), extension->host_permissions()));
+ render_view_host->Send(new ViewMsg_Extension_ExtensionSetIncognitoEnabled(
+ extension->id(), incognito_enabled));
}
ExtensionFunctionDispatcher::~ExtensionFunctionDispatcher() {
@@ -280,8 +286,8 @@ ExtensionFunctionDispatcher::~ExtensionFunctionDispatcher() {
peer_->dispatcher_ = NULL;
}
-Browser* ExtensionFunctionDispatcher::GetBrowser() {
- return delegate_->GetBrowser();
+Browser* ExtensionFunctionDispatcher::GetBrowser(bool include_incognito) {
+ return delegate_->GetBrowser(include_incognito);
}
ExtensionPopupHost* ExtensionFunctionDispatcher::GetPopupHost() {
@@ -324,6 +330,8 @@ void ExtensionFunctionDispatcher::HandleRequest(const std::string& name,
function->SetArgs(args);
function->set_request_id(request_id);
function->set_has_callback(has_callback);
+ function->set_include_incognito(
+ profile()->GetExtensionsService()->IsIncognitoEnabled(extension_id()));
ExtensionsService* service = profile()->GetExtensionsService();
DCHECK(service);
diff --git a/chrome/browser/extensions/extension_function_dispatcher.h b/chrome/browser/extensions/extension_function_dispatcher.h
index 38376e7..1bdfca2 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.h
+++ b/chrome/browser/extensions/extension_function_dispatcher.h
@@ -34,7 +34,10 @@ class ExtensionFunctionDispatcher {
public:
class Delegate {
public:
- virtual Browser* GetBrowser() const = 0;
+ // Returns the browser that this delegate is associated with. If the browser
+ // is incognito, but |include_incognito_windows| is false, we fall back to
+ // the toplevel browser in the original profile.
+ virtual Browser* GetBrowser(bool include_incognito_windows) const = 0;
// Returns the gfx::NativeWindow that contains the view hosting the
// environment in which the function dispatcher resides.
@@ -89,7 +92,9 @@ class ExtensionFunctionDispatcher {
// Gets the browser extension functions should operate relative to. For
// example, for positioning windows, or alert boxes, or creating tabs.
- Browser* GetBrowser();
+ // If |include_incognito| is false, and the appropriate browser is incognito,
+ // we will fall back to a regular browser window or NULL if unavailable.
+ Browser* GetBrowser(bool include_incognito);
// Get the extension popup hosting environment for the ExtensionHost
// or ExtensionDOMUI associted with this dispatcher.
diff --git a/chrome/browser/extensions/extension_history_api.cc b/chrome/browser/extensions/extension_history_api.cc
index c1808d5..75ed48a 100644
--- a/chrome/browser/extensions/extension_history_api.cc
+++ b/chrome/browser/extensions/extension_history_api.cc
@@ -140,8 +140,8 @@ void ExtensionHistoryEventRouter::DispatchEvent(Profile* profile,
const char* event_name,
const std::string& json_args) {
if (profile && profile->GetExtensionMessageService()) {
- profile->GetExtensionMessageService()->
- DispatchEventToRenderers(event_name, json_args);
+ profile->GetExtensionMessageService()->DispatchEventToRenderers(
+ event_name, json_args, profile->IsOffTheRecord());
}
}
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index e139899..5c01d69 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -483,8 +483,8 @@ void ExtensionHost::ProcessDOMUIMessage(const std::string& message,
int request_id,
bool has_callback) {
if (extension_function_dispatcher_.get()) {
- extension_function_dispatcher_->HandleRequest(message, content, request_id,
- has_callback);
+ extension_function_dispatcher_->HandleRequest(
+ message, content, request_id, has_callback);
}
}
@@ -612,19 +612,28 @@ void ExtensionHost::HandleMouseLeave() {
#endif
}
-Browser* ExtensionHost::GetBrowser() const {
+Browser* ExtensionHost::GetBrowser(bool include_incognito) const {
+ Browser* browser = NULL;
+
if (view_.get())
- return view_->browser();
+ browser = view_->browser();
- Profile* profile = render_view_host()->process()->profile();
- Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
+ if (!browser ||
+ (browser->profile()->IsOffTheRecord() && !include_incognito)) {
+ Profile* profile = render_view_host()->process()->profile();
+ // Make sure we don't return an incognito browser without proper access.
+ if (!include_incognito)
+ profile = profile->GetOriginalProfile();
- // It's possible for a browser to exist, but to have never been active.
- // This can happen if you launch the browser on a machine without an active
- // desktop (a headless buildbot) or if you quickly give another app focus
- // at launch time. This is easy to do with browser_tests.
- if (!browser)
- browser = BrowserList::FindBrowserWithProfile(profile);
+ browser = BrowserList::GetLastActiveWithProfile(profile);
+
+ // It's possible for a browser to exist, but to have never been active.
+ // This can happen if you launch the browser on a machine without an active
+ // desktop (a headless buildbot) or if you quickly give another app focus
+ // at launch time. This is easy to do with browser_tests.
+ if (!browser)
+ browser = BrowserList::FindBrowserWithProfile(profile);
+ }
// TODO(erikkay): can this still return NULL? Is Rafael's comment still
// valid here?
diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h
index fd155d7..83f2cb2 100644
--- a/chrome/browser/extensions/extension_host.h
+++ b/chrome/browser/extensions/extension_host.h
@@ -196,10 +196,11 @@ class ExtensionHost : public ExtensionPopupHost::PopupDelegate,
// If this ExtensionHost has a view, this returns the Browser that view is a
// part of. If this is a global background page, we use the active Browser
// instead.
- virtual Browser* GetBrowser() const;
+ virtual Browser* GetBrowser(bool include_incognito) const;
virtual ExtensionHost* GetExtensionHost() { return this; }
// ExtensionPopupHost::Delegate
+ virtual Browser* GetBrowser() const { return GetBrowser(true); }
virtual RenderViewHost* GetRenderViewHost() { return render_view_host(); }
virtual gfx::NativeView GetNativeViewOfHost() {
return view()->native_view();
diff --git a/chrome/browser/extensions/incognito_noscript_apitest.cc b/chrome/browser/extensions/extension_incognito_apitest.cc
index d4e71a5..29de8fb 100755
--- a/chrome/browser/extensions/incognito_noscript_apitest.cc
+++ b/chrome/browser/extensions/extension_incognito_apitest.cc
@@ -5,7 +5,8 @@
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
-#include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/extensions/browser_action_test_util.h"
+#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/extensions/user_script_master.h"
#include "chrome/browser/profile.h"
@@ -24,7 +25,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, IncognitoNoScript) {
CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableExperimentalExtensionApis);
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
- .AppendASCII("incognito_no_script")));
+ .AppendASCII("incognito").AppendASCII("content_scripts")));
// Open incognito window and navigate to test page.
ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
@@ -56,21 +57,13 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, IncognitoYesScript) {
// that loads to "modified".
CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableExperimentalExtensionApis);
- ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
- .AppendASCII("incognito_no_script")));
+ ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_.AppendASCII("api_test")
+ .AppendASCII("incognito").AppendASCII("content_scripts")));
// Dummy extension #2.
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
.AppendASCII("content_scripts").AppendASCII("isolated_world1")));
- // Now enable the incognito_no_script extension in incognito mode, and ensure
- // that page titles are modified.
- ExtensionsService* service = browser()->profile()->GetExtensionsService();
- service->extension_prefs()->SetIsIncognitoEnabled(
- service->extensions()->at(1)->id(), true);
- browser()->profile()->GetUserScriptMaster()->ReloadExtensionForTesting(
- service->extensions()->at(1));
-
// Open incognito window and navigate to test page.
ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
GURL("http://www.example.com:1337/files/extensions/test_file.html"));
@@ -86,3 +79,66 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, IncognitoYesScript) {
&result);
EXPECT_TRUE(result);
}
+
+// Tests that the APIs in an incognito-enabled extension work properly.
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Incognito) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ StartHTTPServer();
+
+ ResultCatcher catcher;
+
+ // Open incognito window and navigate to test page.
+ ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
+ GURL("http://www.example.com:1337/files/extensions/test_file.html"));
+
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableExperimentalExtensionApis);
+ ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
+ .AppendASCII("incognito").AppendASCII("apis")));
+
+ EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
+}
+
+// Tests that the APIs in an incognito-disabled extension don't see incognito
+// events or callbacks.
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoDisabled) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ StartHTTPServer();
+
+ ResultCatcher catcher;
+
+ // Open incognito window and navigate to test page.
+ ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
+ GURL("http://www.example.com:1337/files/extensions/test_file.html"));
+
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableExperimentalExtensionApis);
+ ASSERT_TRUE(LoadExtension(test_data_dir_
+ .AppendASCII("incognito").AppendASCII("apis_disabled")));
+
+ EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
+}
+
+// Test that opening a popup from an incognito browser window works properly.
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoPopup) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ StartHTTPServer();
+
+ ResultCatcher catcher;
+
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableExperimentalExtensionApis);
+ ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
+ .AppendASCII("incognito").AppendASCII("popup")));
+
+ // Open incognito window and navigate to test page.
+ ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
+ GURL("http://www.example.com:1337/files/extensions/test_file.html"));
+ Browser* incognito_browser = BrowserList::FindBrowserWithType(
+ browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL);
+
+ // Simulate the incognito's browser action being clicked.
+ BrowserActionTestUtil(incognito_browser).Press(0);
+
+ EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
+}
diff --git a/chrome/browser/extensions/extension_message_service.cc b/chrome/browser/extensions/extension_message_service.cc
index 9339196..dd464ea 100644
--- a/chrome/browser/extensions/extension_message_service.cc
+++ b/chrome/browser/extensions/extension_message_service.cc
@@ -92,10 +92,12 @@ static void DispatchOnMessage(const ExtensionMessageService::MessagePort& port,
static void DispatchEvent(const ExtensionMessageService::MessagePort& port,
const std::string& event_name,
- const std::string& event_args) {
+ const std::string& event_args,
+ bool has_incognito_data) {
ListValue args;
args.Set(0, Value::CreateStringValue(event_name));
args.Set(1, Value::CreateStringValue(event_args));
+ args.Set(2, Value::CreateBooleanValue(has_incognito_data));
port.sender->Send(new ViewMsg_ExtensionMessageInvoke(
port.routing_id, ExtensionMessageService::kDispatchEvent, args));
}
@@ -283,7 +285,7 @@ void ExtensionMessageService::OpenChannelToTabOnUIThread(
TabContents* contents = NULL;
MessagePort receiver;
receiver.debug_info = 2;
- if (ExtensionTabUtil::GetTabById(tab_id, source->profile(),
+ if (ExtensionTabUtil::GetTabById(tab_id, source->profile(), true,
NULL, NULL, &contents, NULL)) {
receiver.sender = contents->render_view_host();
receiver.routing_id = contents->render_view_host()->routing_id();
@@ -451,7 +453,8 @@ void ExtensionMessageService::PostMessageFromRenderer(
}
void ExtensionMessageService::DispatchEventToRenderers(
- const std::string& event_name, const std::string& event_args) {
+ const std::string& event_name, const std::string& event_args,
+ bool has_incognito_data) {
DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
std::set<int>& pids = listeners_[event_name];
@@ -467,7 +470,7 @@ void ExtensionMessageService::DispatchEventToRenderers(
continue;
}
- DispatchEvent(renderer, event_name, event_args);
+ DispatchEvent(renderer, event_name, event_args, has_incognito_data);
}
}
diff --git a/chrome/browser/extensions/extension_message_service.h b/chrome/browser/extensions/extension_message_service.h
index b04780c..6b8ade6 100644
--- a/chrome/browser/extensions/extension_message_service.h
+++ b/chrome/browser/extensions/extension_message_service.h
@@ -82,7 +82,8 @@ class ExtensionMessageService
// Send an event to every registered extension renderer.
void DispatchEventToRenderers(
- const std::string& event_name, const std::string& event_args);
+ const std::string& event_name, const std::string& event_args,
+ bool has_incognito_data);
// Given an extension ID, opens a channel between the given
// automation "port" or DevTools service and that extension. the
diff --git a/chrome/browser/extensions/extension_page_actions_module.cc b/chrome/browser/extensions/extension_page_actions_module.cc
index 1379b2f..5fcbf45 100644
--- a/chrome/browser/extensions/extension_page_actions_module.cc
+++ b/chrome/browser/extensions/extension_page_actions_module.cc
@@ -70,7 +70,8 @@ bool PageActionFunction::SetPageActionEnabled(bool enable) {
// Find the TabContents that contains this tab id.
TabContents* contents = NULL;
- ExtensionTabUtil::GetTabById(tab_id, profile(), NULL, NULL, &contents, NULL);
+ ExtensionTabUtil::GetTabById(tab_id, profile(), include_incognito(),
+ NULL, NULL, &contents, NULL);
if (!contents) {
error_ = ExtensionErrorUtils::FormatErrorMessage(kNoTabError,
IntToString(tab_id));
@@ -102,7 +103,8 @@ bool PageActionFunction::InitCommon(int tab_id) {
// Find the TabContents that contains this tab id.
contents_ = NULL;
- ExtensionTabUtil::GetTabById(tab_id, profile(), NULL, NULL, &contents_, NULL);
+ ExtensionTabUtil::GetTabById(tab_id, profile(), include_incognito(),
+ NULL, NULL, &contents_, NULL);
if (!contents_) {
error_ = ExtensionErrorUtils::FormatErrorMessage(kNoTabError,
IntToString(tab_id));
diff --git a/chrome/browser/extensions/extension_popup_api.cc b/chrome/browser/extensions/extension_popup_api.cc
index 48e414c..d6edbc0 100644
--- a/chrome/browser/extensions/extension_popup_api.cc
+++ b/chrome/browser/extensions/extension_popup_api.cc
@@ -155,7 +155,7 @@ bool PopupShowFunction::RunImpl() {
BubbleBorder::ArrowLocation arrow_location =
(NULL != dispatcher()->GetExtensionHost()) ? BubbleBorder::BOTTOM_LEFT :
BubbleBorder::TOP_LEFT;
- popup_ = ExtensionPopup::Show(url, dispatcher()->GetBrowser(),
+ popup_ = ExtensionPopup::Show(url, GetBrowser(),
dispatcher()->profile(),
dispatcher()->GetFrameNativeWindow(),
rect,
@@ -238,5 +238,6 @@ void PopupEventRouter::OnPopupClosed(Profile* profile,
profile->GetExtensionMessageService()->DispatchEventToRenderers(
full_event_name,
- base::JSONWriter::kEmptyArray);
+ base::JSONWriter::kEmptyArray,
+ profile->IsOffTheRecord());
}
diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc
index 3121d3c..7ecee27 100644
--- a/chrome/browser/extensions/extension_process_manager.cc
+++ b/chrome/browser/extensions/extension_process_manager.cc
@@ -232,6 +232,19 @@ void ExtensionProcessManager::Observe(NotificationType type,
break;
}
+ case NotificationType::EXTENSION_INCOGNITO_CHANGED: {
+ Extension* extension =
+ Details<std::pair<Extension*, bool> >(details).ptr()->first;
+ bool incognito_enabled =
+ Details<std::pair<Extension*, bool> >(details).ptr()->second;
+ RenderProcessHost* rph = GetExtensionProcess(extension->id());
+ if (rph) {
+ rph->Send(new ViewMsg_Extension_ExtensionSetIncognitoEnabled(
+ extension->id(), incognito_enabled));
+ }
+ break;
+ }
+
case NotificationType::EXTENSION_HOST_DESTROYED: {
ExtensionHost* host = Details<ExtensionHost>(details).ptr();
all_hosts_.erase(host);
diff --git a/chrome/browser/extensions/extension_processes_api.cc b/chrome/browser/extensions/extension_processes_api.cc
index 8495d9d..fda8c7f 100644
--- a/chrome/browser/extensions/extension_processes_api.cc
+++ b/chrome/browser/extensions/extension_processes_api.cc
@@ -24,8 +24,8 @@ bool GetProcessForTabFunction::RunImpl() {
TabContents* contents = NULL;
int tab_index = -1;
- if (!ExtensionTabUtil::GetTabById(tab_id, profile(), NULL, NULL,
- &contents, &tab_index))
+ if (!ExtensionTabUtil::GetTabById(tab_id, profile(), include_incognito(),
+ NULL, NULL, &contents, &tab_index))
return false;
int process_id = contents->GetRenderProcessHost()->id();
diff --git a/chrome/browser/extensions/extension_protocols.cc b/chrome/browser/extensions/extension_protocols.cc
index 21dcd12..b6e66f6 100644
--- a/chrome/browser/extensions/extension_protocols.cc
+++ b/chrome/browser/extensions/extension_protocols.cc
@@ -6,12 +6,16 @@
#include "base/string_util.h"
#include "chrome/browser/net/chrome_url_request_context.h"
+#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
+#include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_file_util.h"
#include "chrome/common/extensions/extension_resource.h"
#include "chrome/common/url_constants.h"
#include "googleurl/src/url_util.h"
+#include "net/base/net_errors.h"
#include "net/url_request/url_request_file_job.h"
+#include "net/url_request/url_request_error_job.h"
// Factory registered with URLRequest to create URLRequestJobs for extension://
// URLs.
@@ -20,6 +24,16 @@ static URLRequestJob* CreateExtensionURLRequestJob(URLRequest* request,
ChromeURLRequestContext* context =
static_cast<ChromeURLRequestContext*>(request->context());
+ // Don't allow toplevel navigations to extension resources in incognito mode.
+ // This is because an extension must run in a single process, and an incognito
+ // tab prevents that.
+ // TODO(mpcomplete): better error code.
+ const ResourceDispatcherHostRequestInfo* info =
+ ResourceDispatcherHost::InfoForRequest(request);
+ if (context->is_off_the_record() &&
+ info && info->resource_type() == ResourceType::MAIN_FRAME)
+ return new URLRequestErrorJob(request, net::ERR_ADDRESS_UNREACHABLE);
+
// chrome-extension://extension-id/resource/path.js
FilePath directory_path = context->GetPathForExtension(request->url().host());
if (directory_path.value().empty()) {
diff --git a/chrome/browser/extensions/extension_tabs_module.cc b/chrome/browser/extensions/extension_tabs_module.cc
index e00964d..c602cf6 100644
--- a/chrome/browser/extensions/extension_tabs_module.cc
+++ b/chrome/browser/extensions/extension_tabs_module.cc
@@ -36,11 +36,14 @@ namespace keys = extension_tabs_module_constants;
// message if the window cannot be found by id.
static Browser* GetBrowserInProfileWithId(Profile* profile,
const int window_id,
+ bool include_incognito,
std::string* error_message);
-// |error_message| can optionally be passed in a will be set with an appropriate
-// message if the tab cannot be found by id.
-static bool GetTabById(int tab_id, Profile* profile, Browser** browser,
+// |error_message| can optionally be passed in and will be set with an
+// appropriate message if the tab cannot be found by id.
+static bool GetTabById(int tab_id, Profile* profile,
+ bool include_incognito,
+ Browser** browser,
TabStripModel** tab_strip,
TabContents** contents,
int* tab_index, std::string* error_message);
@@ -117,6 +120,8 @@ DictionaryValue* ExtensionTabUtil::CreateTabValue(
result->SetBoolean(keys::kSelectedKey,
tab_strip && tab_index == tab_strip->selected_index());
result->SetString(keys::kTitleKey, UTF16ToWide(contents->GetTitle()));
+ result->SetBoolean(keys::kIncognitoKey,
+ contents->profile()->IsOffTheRecord());
if (status != TAB_LOADING) {
NavigationEntry* entry = contents->controller().GetActiveEntry();
@@ -140,6 +145,8 @@ DictionaryValue* ExtensionTabUtil::CreateWindowValue(const Browser* browser,
if (browser->window())
focused = browser->window()->IsActive();
+ result->SetBoolean(keys::kIncognitoKey,
+ browser->profile()->IsOffTheRecord());
result->SetBoolean(keys::kFocusedKey, focused);
gfx::Rect bounds = browser->window()->GetRestoredBounds();
@@ -173,6 +180,7 @@ bool ExtensionTabUtil::GetDefaultTab(Browser* browser, TabContents** contents,
}
bool ExtensionTabUtil::GetTabById(int tab_id, Profile* profile,
+ bool include_incognito,
Browser** browser,
TabStripModel** tab_strip,
TabContents** contents,
@@ -180,10 +188,13 @@ bool ExtensionTabUtil::GetTabById(int tab_id, Profile* profile,
Browser* target_browser;
TabStripModel* target_tab_strip;
TabContents* target_contents;
+ Profile* incognito_profile =
+ include_incognito ? profile->GetOffTheRecordProfile() : NULL;
for (BrowserList::const_iterator iter = BrowserList::begin();
iter != BrowserList::end(); ++iter) {
target_browser = *iter;
- if (target_browser->profile() == profile) {
+ if (target_browser->profile() == profile ||
+ target_browser->profile() == incognito_profile) {
target_tab_strip = target_browser->tabstrip_model();
for (int i = 0; i < target_tab_strip->count(); ++i) {
target_contents = target_tab_strip->GetTabContentsAt(i);
@@ -210,7 +221,8 @@ bool GetWindowFunction::RunImpl() {
int window_id;
EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&window_id));
- Browser* browser = GetBrowserInProfileWithId(profile(), window_id, &error_);
+ Browser* browser = GetBrowserInProfileWithId(profile(), window_id,
+ include_incognito(), &error_);
if (!browser)
return false;
@@ -219,7 +231,7 @@ bool GetWindowFunction::RunImpl() {
}
bool GetCurrentWindowFunction::RunImpl() {
- Browser* browser = dispatcher()->GetBrowser();
+ Browser* browser = GetBrowser();
if (!browser) {
error_ = keys::kNoCurrentWindowError;
return false;
@@ -250,10 +262,13 @@ bool GetAllWindowsFunction::RunImpl() {
}
result_.reset(new ListValue());
+ Profile* incognito_profile =
+ include_incognito() ? profile()->GetOffTheRecordProfile() : NULL;
for (BrowserList::const_iterator browser = BrowserList::begin();
browser != BrowserList::end(); ++browser) {
// Only examine browsers in the current profile.
- if ((*browser)->profile() == profile()) {
+ if ((*browser)->profile() == profile() ||
+ (*browser)->profile() == incognito_profile) {
static_cast<ListValue*>(result_.get())->
Append(ExtensionTabUtil::CreateWindowValue(*browser, populate_tabs));
}
@@ -297,7 +312,7 @@ bool CreateWindowFunction::RunImpl() {
// NOTE(rafaelw): It's ok if dispatcher_->GetBrowser() returns NULL here.
// GetBrowserWindowBounds will default to saved "default" values for the app.
WindowSizer::GetBrowserWindowBounds(std::wstring(), empty_bounds,
- dispatcher()->GetBrowser(), &bounds,
+ GetBrowser(), &bounds,
&maximized);
// Any part of the bounds can optionally be set by the caller.
@@ -351,7 +366,8 @@ bool UpdateWindowFunction::RunImpl() {
DictionaryValue* update_props;
EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &update_props));
- Browser* browser = GetBrowserInProfileWithId(profile(), window_id, &error_);
+ Browser* browser = GetBrowserInProfileWithId(profile(), window_id,
+ include_incognito(), &error_);
if (!browser)
return false;
@@ -397,7 +413,8 @@ bool RemoveWindowFunction::RunImpl() {
int window_id;
EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&window_id));
- Browser* browser = GetBrowserInProfileWithId(profile(), window_id, &error_);
+ Browser* browser = GetBrowserInProfileWithId(profile(), window_id,
+ include_incognito(), &error_);
if (!browser)
return false;
@@ -415,9 +432,10 @@ bool GetSelectedTabFunction::RunImpl() {
if (!args_->IsType(Value::TYPE_NULL)) {
EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&window_id));
- browser = GetBrowserInProfileWithId(profile(), window_id, &error_);
+ browser = GetBrowserInProfileWithId(profile(), window_id,
+ include_incognito(), &error_);
} else {
- browser = dispatcher()->GetBrowser();
+ browser = GetBrowser();
if (!browser)
error_ = keys::kNoCurrentWindowError;
}
@@ -441,9 +459,10 @@ bool GetAllTabsInWindowFunction::RunImpl() {
int window_id = -1;
if (!args_->IsType(Value::TYPE_NULL)) {
EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&window_id));
- browser = GetBrowserInProfileWithId(profile(), window_id, &error_);
+ browser = GetBrowserInProfileWithId(profile(), window_id,
+ include_incognito(), &error_);
} else {
- browser = dispatcher()->GetBrowser();
+ browser = GetBrowser();
if (!browser)
error_ = keys::kNoCurrentWindowError;
}
@@ -465,9 +484,10 @@ bool CreateTabFunction::RunImpl() {
if (args->HasKey(keys::kWindowIdKey)) {
EXTENSION_FUNCTION_VALIDATE(args->GetInteger(
keys::kWindowIdKey, &window_id));
- browser = GetBrowserInProfileWithId(profile(), window_id, &error_);
+ browser = GetBrowserInProfileWithId(profile(), window_id,
+ include_incognito(), &error_);
} else {
- browser = dispatcher()->GetBrowser();
+ browser = GetBrowser();
if (!browser)
error_ = keys::kNoCurrentWindowError;
}
@@ -536,8 +556,8 @@ bool GetTabFunction::RunImpl() {
TabStripModel* tab_strip = NULL;
TabContents* contents = NULL;
int tab_index = -1;
- if (!GetTabById(tab_id, profile(), NULL, &tab_strip, &contents, &tab_index,
- &error_))
+ if (!GetTabById(tab_id, profile(), include_incognito(),
+ NULL, &tab_strip, &contents, &tab_index, &error_))
return false;
result_.reset(ExtensionTabUtil::CreateTabValue(contents, tab_strip,
@@ -556,8 +576,8 @@ bool UpdateTabFunction::RunImpl() {
TabStripModel* tab_strip = NULL;
TabContents* contents = NULL;
int tab_index = -1;
- if (!GetTabById(tab_id, profile(), NULL, &tab_strip, &contents, &tab_index,
- &error_))
+ if (!GetTabById(tab_id, profile(), include_incognito(),
+ NULL, &tab_strip, &contents, &tab_index, &error_))
return false;
if (tab_strip->IsTabPinned(tab_index)) {
@@ -645,8 +665,9 @@ bool MoveTabFunction::RunImpl() {
TabStripModel* source_tab_strip = NULL;
TabContents* contents = NULL;
int tab_index = -1;
- if (!GetTabById(tab_id, profile(), &source_browser, &source_tab_strip,
- &contents, &tab_index, &error_))
+ if (!GetTabById(tab_id, profile(), include_incognito(),
+ &source_browser, &source_tab_strip, &contents,
+ &tab_index, &error_))
return false;
if (update_props->HasKey(keys::kWindowIdKey)) {
@@ -655,7 +676,7 @@ bool MoveTabFunction::RunImpl() {
EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger(
keys::kWindowIdKey, &window_id));
target_browser = GetBrowserInProfileWithId(profile(), window_id,
- &error_);
+ include_incognito(), &error_);
if (!target_browser)
return false;
@@ -708,7 +729,8 @@ bool RemoveTabFunction::RunImpl() {
Browser* browser = NULL;
TabContents* contents = NULL;
- if (!GetTabById(tab_id, profile(), &browser, NULL, &contents, NULL, &error_))
+ if (!GetTabById(tab_id, profile(), include_incognito(),
+ &browser, NULL, &contents, NULL, &error_))
return false;
int tab_index = browser->GetIndexOfController(&contents->controller());
@@ -734,9 +756,10 @@ bool CaptureVisibleTabFunction::RunImpl() {
if (!args_->IsType(Value::TYPE_NULL)) {
EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&window_id));
- browser = GetBrowserInProfileWithId(profile(), window_id, &error_);
+ browser = GetBrowserInProfileWithId(profile(), window_id,
+ include_incognito(), &error_);
} else {
- browser = dispatcher()->GetBrowser();
+ browser = GetBrowser();
}
if (!browser) {
@@ -856,14 +879,14 @@ bool DetectTabLanguageFunction::RunImpl() {
// in the current window.
if (!args_->IsType(Value::TYPE_NULL)) {
EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&tab_id));
- if (!GetTabById(tab_id, profile(), &browser, NULL, &contents, NULL,
- &error_)) {
+ if (!GetTabById(tab_id, profile(), include_incognito(),
+ &browser, NULL, &contents, NULL, &error_)) {
return false;
}
if (!browser || !contents)
return false;
} else {
- browser = dispatcher()->GetBrowser();
+ browser = GetBrowser();
if (!browser)
return false;
contents = browser->tabstrip_model()->GetSelectedTabContents();
@@ -924,10 +947,14 @@ void DetectTabLanguageFunction::GotLanguage(const std::string& language) {
static Browser* GetBrowserInProfileWithId(Profile* profile,
const int window_id,
+ bool include_incognito,
std::string* error_message) {
+ Profile* incognito_profile =
+ include_incognito ? profile->GetOffTheRecordProfile() : NULL;
for (BrowserList::const_iterator browser = BrowserList::begin();
- browser != BrowserList::end(); ++browser) {
- if ((*browser)->profile() == profile &&
+ browser != BrowserList::end(); ++browser) {
+ if (((*browser)->profile() == profile ||
+ (*browser)->profile() == incognito_profile) &&
ExtensionTabUtil::GetWindowId(*browser) == window_id)
return *browser;
}
@@ -939,13 +966,15 @@ static Browser* GetBrowserInProfileWithId(Profile* profile,
return NULL;
}
-static bool GetTabById(int tab_id, Profile* profile, Browser** browser,
+static bool GetTabById(int tab_id, Profile* profile,
+ bool include_incognito,
+ Browser** browser,
TabStripModel** tab_strip,
TabContents** contents,
int* tab_index,
std::string* error_message) {
- if (ExtensionTabUtil::GetTabById(tab_id, profile, browser, tab_strip,
- contents, tab_index))
+ if (ExtensionTabUtil::GetTabById(tab_id, profile, include_incognito,
+ browser, tab_strip, contents, tab_index))
return true;
if (error_message)
diff --git a/chrome/browser/extensions/extension_tabs_module.h b/chrome/browser/extensions/extension_tabs_module.h
index 5282a17..c7d36f8 100644
--- a/chrome/browser/extensions/extension_tabs_module.h
+++ b/chrome/browser/extensions/extension_tabs_module.h
@@ -45,7 +45,8 @@ class ExtensionTabUtil {
int* tab_id);
// Any out parameter (|browser|, |tab_strip|, |contents|, & |tab_index|) may
// be NULL and will not be set within the function.
- static bool GetTabById(int tab_id, Profile* profile, Browser** browser,
+ static bool GetTabById(int tab_id, Profile* profile, bool incognito_enabled,
+ Browser** browser,
TabStripModel** tab_strip,
TabContents** contents,
int* tab_index);
diff --git a/chrome/browser/extensions/extension_tabs_module_constants.cc b/chrome/browser/extensions/extension_tabs_module_constants.cc
index 96176ea..6a75742 100644
--- a/chrome/browser/extensions/extension_tabs_module_constants.cc
+++ b/chrome/browser/extensions/extension_tabs_module_constants.cc
@@ -32,6 +32,7 @@ const wchar_t kTopKey[] = L"top";
const wchar_t kUrlKey[] = L"url";
const wchar_t kWidthKey[] = L"width";
const wchar_t kWindowIdKey[] = L"windowId";
+const wchar_t kIncognitoKey[] = L"incognito";
const char kStatusValueComplete[] = "complete";
const char kStatusValueLoading[] = "loading";
diff --git a/chrome/browser/extensions/extension_tabs_module_constants.h b/chrome/browser/extensions/extension_tabs_module_constants.h
index f51bc5a..9f72501 100644
--- a/chrome/browser/extensions/extension_tabs_module_constants.h
+++ b/chrome/browser/extensions/extension_tabs_module_constants.h
@@ -36,6 +36,7 @@ extern const wchar_t kTopKey[];
extern const wchar_t kUrlKey[];
extern const wchar_t kWidthKey[];
extern const wchar_t kWindowIdKey[];
+extern const wchar_t kIncognitoKey[];
// Value consts.
extern const char kStatusValueComplete[];
diff --git a/chrome/browser/extensions/extension_test_api.cc b/chrome/browser/extensions/extension_test_api.cc
index ac0a2eb..48323d4 100644
--- a/chrome/browser/extensions/extension_test_api.cc
+++ b/chrome/browser/extensions/extension_test_api.cc
@@ -2,10 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "chrome/browser/extensions/extension_test_api.h"
+
+#include "chrome/browser/browser.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/extensions/extensions_quota_service.h"
-#include "chrome/browser/extensions/extension_test_api.h"
#include "chrome/common/notification_service.h"
bool ExtensionTestPassFunction::RunImpl() {
@@ -41,3 +43,10 @@ bool ExtensionTestQuotaResetFunction::RunImpl() {
quota->violators_.clear();
return true;
}
+
+bool ExtensionTestCreateIncognitoTabFunction::RunImpl() {
+ std::string url;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetAsString(&url));
+ Browser::OpenURLOffTheRecord(profile(), GURL(url));
+ return true;
+}
diff --git a/chrome/browser/extensions/extension_test_api.h b/chrome/browser/extensions/extension_test_api.h
index 3b89e53..ee62627 100644
--- a/chrome/browser/extensions/extension_test_api.h
+++ b/chrome/browser/extensions/extension_test_api.h
@@ -31,4 +31,10 @@ class ExtensionTestQuotaResetFunction : public SyncExtensionFunction {
DECLARE_EXTENSION_FUNCTION_NAME("test.resetQuota")
};
+class ExtensionTestCreateIncognitoTabFunction : public SyncExtensionFunction {
+ ~ExtensionTestCreateIncognitoTabFunction() {}
+ virtual bool RunImpl();
+ DECLARE_EXTENSION_FUNCTION_NAME("test.createIncognitoTab")
+};
+
#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_TEST_API_H_
diff --git a/chrome/browser/extensions/extension_toolstrip_api.cc b/chrome/browser/extensions/extension_toolstrip_api.cc
index 18d1839..56ad0a2 100644
--- a/chrome/browser/extensions/extension_toolstrip_api.cc
+++ b/chrome/browser/extensions/extension_toolstrip_api.cc
@@ -40,7 +40,7 @@ bool ToolstripFunction::RunImpl() {
error_ = kNotAToolstripError;
return false;
}
- Browser* browser = dispatcher()->GetBrowser();
+ Browser* browser = GetBrowser();
if (!browser) {
error_ = kNotAToolstripError;
return false;
@@ -133,8 +133,8 @@ void ToolstripEventRouter::DispatchEvent(Profile *profile,
std::string json_args;
base::JSONWriter::Write(&json, false, &json_args);
std::string full_event_name = StringPrintf(event_name, routing_id);
- profile->GetExtensionMessageService()->
- DispatchEventToRenderers(full_event_name, json_args);
+ profile->GetExtensionMessageService()->DispatchEventToRenderers(
+ full_event_name, json_args, profile->IsOffTheRecord());
}
}
diff --git a/chrome/browser/extensions/extension_ui_unittest.cc b/chrome/browser/extensions/extension_ui_unittest.cc
index 4bffb44..f1bd648 100644
--- a/chrome/browser/extensions/extension_ui_unittest.cc
+++ b/chrome/browser/extensions/extension_ui_unittest.cc
@@ -50,8 +50,8 @@ namespace {
// Produce test output.
scoped_ptr<DictionaryValue> actual_output_data(
- ExtensionsDOMHandler::CreateExtensionDetailValue(&extension, pages,
- true));
+ ExtensionsDOMHandler::CreateExtensionDetailValue(NULL, &extension,
+ pages, true));
// Compare the outputs.
return expected_output_data->Equals(actual_output_data.get());
diff --git a/chrome/browser/extensions/extension_uitest.cc b/chrome/browser/extensions/extension_uitest.cc
index 8192968..5537dc4 100644
--- a/chrome/browser/extensions/extension_uitest.cc
+++ b/chrome/browser/extensions/extension_uitest.cc
@@ -218,8 +218,10 @@ public:
tab_dict.SetInteger(extension_tabs_module_constants::kIndexKey, 1);
tab_dict.SetInteger(extension_tabs_module_constants::kWindowIdKey, 1);
tab_dict.SetBoolean(extension_tabs_module_constants::kSelectedKey, true);
+ tab_dict.SetBoolean(extension_tabs_module_constants::kIncognitoKey,
+ false);
tab_dict.SetString(extension_tabs_module_constants::kUrlKey,
- "http://www.google.com");
+ "http://www.google.com");
std::string tab_json;
base::JSONWriter::Write(&tab_dict, false, &tab_json);
@@ -327,7 +329,7 @@ class ExtensionTestBrowserEvents : public ExtensionUITest {
const char* ExtensionTestBrowserEvents::events_[] = {
// Window events.
"[\"windows.onCreated\", \"[{'id':42,'focused':true,'top':0,'left':0,"
- "'width':100,'height':100}]\"]",
+ "'width':100,'height':100,'incognito':false}]\"]",
"[\"windows.onRemoved\", \"[42]\"]",
@@ -335,11 +337,11 @@ const char* ExtensionTestBrowserEvents::events_[] = {
// Tab events.
"[\"tabs.onCreated\", \"[{'id':42,'index':1,'windowId':1,"
- "'selected':true,'url':'http://www.google.com'}]\"]",
+ "'selected':true,'url':'http://www.google.com','incognito':false}]\"]",
"[\"tabs.onUpdated\", \"[42, {'status': 'complete',"
"'url':'http://www.google.com'}, {'id':42,'index':1,'windowId':1,"
- "'selected':true,'url':'http://www.google.com'}]\"]",
+ "'selected':true,'url':'http://www.google.com','incognito':false}]\"]",
"[\"tabs.onMoved\", \"[42, {'windowId':1,'fromIndex':1,'toIndex':2}]\"]",
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index d171767..9cf2fb9 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -530,13 +530,19 @@ base::Time ExtensionsService::LastPingDay(const std::string& extension_id) {
}
bool ExtensionsService::IsIncognitoEnabled(const std::string& extension_id) {
- Extension* extension = GetExtensionById(extension_id, true);
- if (!extension)
- return false;
+ return extension_prefs_->IsIncognitoEnabled(extension_id);
+}
+
+void ExtensionsService::SetIsIncognitoEnabled(const std::string& extension_id,
+ bool enabled) {
+ Extension* extension = GetExtensionByIdInternal(extension_id, true, true);
+ extension_prefs_->SetIsIncognitoEnabled(extension_id, enabled);
- return extension_prefs_->IsIncognitoEnabled(extension_id) &&
- extension->HasApiPermission(Extension::kExperimentalPermission) &&
- extension->HasApiPermission(Extension::kIncognitoPermission);
+ std::pair<Extension*, bool> details(extension, enabled);
+ NotificationService::current()->Notify(
+ NotificationType::EXTENSION_INCOGNITO_CHANGED,
+ Source<Profile>(profile_),
+ Details<std::pair<Extension*, bool> >(&details));
}
void ExtensionsService::CheckForExternalUpdates() {
diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h
index 078ac01..a95d0aa 100644
--- a/chrome/browser/extensions/extensions_service.h
+++ b/chrome/browser/extensions/extensions_service.h
@@ -106,10 +106,9 @@ class ExtensionsService
const base::Time& time);
virtual base::Time LastPingDay(const std::string& extension_id);
- // Returns true if this extension can run in an incognito window. The
- // decision is based on both user consent and the extension having the right
- // permission.
+ // Whether this extension can run in an incognito window.
bool IsIncognitoEnabled(const std::string& extension_id);
+ void SetIsIncognitoEnabled(const std::string& extension_id, bool enabled);
const FilePath& install_directory() const { return install_directory_; }
diff --git a/chrome/browser/extensions/extensions_ui.cc b/chrome/browser/extensions/extensions_ui.cc
index 24dc43e..4201c17 100644
--- a/chrome/browser/extensions/extensions_ui.cc
+++ b/chrome/browser/extensions/extensions_ui.cc
@@ -31,6 +31,7 @@
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_error_reporter.h"
@@ -100,6 +101,12 @@ void ExtensionsUIHTMLSource::StartDataRequest(const std::string& path,
l10n_util::GetString(IDS_EXTENSIONS_DISABLE));
localized_strings.SetString(L"enable",
l10n_util::GetString(IDS_EXTENSIONS_ENABLE));
+ localized_strings.SetString(L"disableIncognito",
+ l10n_util::GetString(IDS_EXTENSIONS_DISABLE_INCOGNITO));
+ localized_strings.SetString(L"enableIncognito",
+ l10n_util::GetString(IDS_EXTENSIONS_ENABLE_INCOGNITO));
+ localized_strings.SetString(L"enableIncognitoWarning",
+ l10n_util::GetString(IDS_EXTENSIONS_ENABLE_INCOGNITO_WARNING));
localized_strings.SetString(L"reload",
l10n_util::GetString(IDS_EXTENSIONS_RELOAD));
localized_strings.SetString(L"uninstall",
@@ -251,6 +258,8 @@ void ExtensionsDOMHandler::RegisterMessages() {
NewCallback(this, &ExtensionsDOMHandler::HandleReloadMessage));
dom_ui_->RegisterMessageCallback("enable",
NewCallback(this, &ExtensionsDOMHandler::HandleEnableMessage));
+ dom_ui_->RegisterMessageCallback("enableIncognito",
+ NewCallback(this, &ExtensionsDOMHandler::HandleEnableIncognitoMessage));
dom_ui_->RegisterMessageCallback("uninstall",
NewCallback(this, &ExtensionsDOMHandler::HandleUninstallMessage));
dom_ui_->RegisterMessageCallback("options",
@@ -284,6 +293,7 @@ void ExtensionsDOMHandler::HandleRequestExtensionsData(const Value* value) {
// themes.
if (!(*extension)->IsTheme()) {
extensions_list->Append(CreateExtensionDetailValue(
+ extensions_service_.get(),
*extension, GetActivePagesForExtension((*extension)->id()), true));
extension_icons->push_back(PickExtensionIcon(*extension));
}
@@ -293,6 +303,7 @@ void ExtensionsDOMHandler::HandleRequestExtensionsData(const Value* value) {
extension != extensions->end(); ++extension) {
if (!(*extension)->IsTheme()) {
extensions_list->Append(CreateExtensionDetailValue(
+ extensions_service_.get(),
*extension, GetActivePagesForExtension((*extension)->id()), false));
extension_icons->push_back(PickExtensionIcon(*extension));
}
@@ -303,6 +314,10 @@ void ExtensionsDOMHandler::HandleRequestExtensionsData(const Value* value) {
->GetBoolean(prefs::kExtensionsUIDeveloperMode);
results->SetBoolean(L"developerMode", developer_mode);
+ results->SetBoolean(L"experimentalIncognito",
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalExtensionApis));
+
if (icon_loader_.get())
icon_loader_->Cancel();
@@ -402,6 +417,17 @@ void ExtensionsDOMHandler::HandleEnableMessage(const Value* value) {
}
}
+void ExtensionsDOMHandler::HandleEnableIncognitoMessage(const Value* value) {
+ CHECK(value->IsType(Value::TYPE_LIST));
+ const ListValue* list = static_cast<const ListValue*>(value);
+ CHECK(list->GetSize() == 2);
+ std::string extension_id, enable_str;
+ CHECK(list->GetString(0, &extension_id));
+ CHECK(list->GetString(1, &enable_str));
+ extensions_service_->SetIsIncognitoEnabled(extension_id,
+ (enable_str == "true"));
+}
+
void ExtensionsDOMHandler::HandleUninstallMessage(const Value* value) {
CHECK(value->IsType(Value::TYPE_LIST));
const ListValue* list = static_cast<const ListValue*>(value);
@@ -657,8 +683,8 @@ DictionaryValue* ExtensionsDOMHandler::CreateContentScriptDetailValue(
// Static
DictionaryValue* ExtensionsDOMHandler::CreateExtensionDetailValue(
- const Extension *extension, const std::vector<ExtensionPage>& pages,
- bool enabled) {
+ ExtensionsService* service, const Extension *extension,
+ const std::vector<ExtensionPage>& pages, bool enabled) {
DictionaryValue* extension_data = new DictionaryValue();
extension_data->SetString(L"id", extension->id());
@@ -666,6 +692,10 @@ DictionaryValue* ExtensionsDOMHandler::CreateExtensionDetailValue(
extension_data->SetString(L"description", extension->description());
extension_data->SetString(L"version", extension->version()->GetString());
extension_data->SetBoolean(L"enabled", enabled);
+ extension_data->SetBoolean(L"enabledIncognito",
+ service ? service->IsIncognitoEnabled(extension->id()) : false);
+ extension_data->SetBoolean(L"incognitoSafe",
+ extension->HasApiPermission(Extension::kIncognitoPermission));
extension_data->SetBoolean(L"allow_reload",
extension->location() == Extension::LOAD);
diff --git a/chrome/browser/extensions/extensions_ui.h b/chrome/browser/extensions/extensions_ui.h
index cabc5be..decdc64 100644
--- a/chrome/browser/extensions/extensions_ui.h
+++ b/chrome/browser/extensions/extensions_ui.h
@@ -106,9 +106,11 @@ class ExtensionsDOMHandler
virtual void RegisterMessages();
// Extension Detail JSON Struct for page. (static for ease of testing).
+ // Note: service can be NULL in unit tests.
static DictionaryValue* CreateExtensionDetailValue(
- const Extension *extension,
- const std::vector<ExtensionPage>&,
+ ExtensionsService* service,
+ const Extension* extension,
+ const std::vector<ExtensionPage>& pages,
bool enabled);
// ContentScript JSON Struct for page. (static for ease of testing).
@@ -143,6 +145,9 @@ class ExtensionsDOMHandler
// Callback for "enable" message.
void HandleEnableMessage(const Value* value);
+ // Callback for "enableIncognito" message.
+ void HandleEnableIncognitoMessage(const Value* value);
+
// Callback for "uninstall" message.
void HandleUninstallMessage(const Value* value);
diff --git a/chrome/browser/extensions/user_script_master.cc b/chrome/browser/extensions/user_script_master.cc
index a7d69f6..9506efd 100644
--- a/chrome/browser/extensions/user_script_master.cc
+++ b/chrome/browser/extensions/user_script_master.cc
@@ -294,6 +294,8 @@ UserScriptMaster::UserScriptMaster(const FilePath& script_dir, Profile* profile)
Source<Profile>(profile_));
registrar_.Add(this, NotificationType::EXTENSION_LOADED,
Source<Profile>(profile_));
+ registrar_.Add(this, NotificationType::EXTENSION_INCOGNITO_CHANGED,
+ Source<Profile>(profile_));
registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
Source<Profile>(profile_));
}
@@ -348,6 +350,22 @@ void UserScriptMaster::Observe(NotificationType type,
StartScan();
break;
}
+ case NotificationType::EXTENSION_INCOGNITO_CHANGED: {
+ // Toggle the incognito_enabled bit for any content scripts inside the
+ // extension.
+ Extension* extension =
+ Details<std::pair<Extension*, bool> >(details).ptr()->first;
+ bool incognito_enabled =
+ Details<std::pair<Extension*, bool> >(details).ptr()->second;
+ for (UserScriptList::iterator iter = lone_scripts_.begin();
+ iter != lone_scripts_.end(); ++iter) {
+ if (iter->extension_id() == extension->id())
+ (*iter).set_incognito_enabled(incognito_enabled);
+ }
+ if (extensions_service_ready_)
+ StartScan();
+ break;
+ }
case NotificationType::EXTENSION_UNLOADED: {
// Remove any content scripts.
@@ -378,14 +396,3 @@ void UserScriptMaster::StartScan() {
script_reloader_->StartScan(user_script_dir_, lone_scripts_);
}
-
-void UserScriptMaster::ReloadExtensionForTesting(Extension* extension) {
- bool incognito_enabled = profile_->GetExtensionsService()->
- IsIncognitoEnabled(extension->id());
- for (UserScriptList::iterator iter = lone_scripts_.begin();
- iter != lone_scripts_.end(); ++iter) {
- if (iter->extension_id() == extension->id())
- (*iter).set_incognito_enabled(incognito_enabled);
- }
- StartScan();
-}
diff --git a/chrome/browser/extensions/user_script_master.h b/chrome/browser/extensions/user_script_master.h
index 19562f0..cc0b437 100644
--- a/chrome/browser/extensions/user_script_master.h
+++ b/chrome/browser/extensions/user_script_master.h
@@ -47,11 +47,6 @@ class UserScriptMaster : public base::RefCountedThreadSafe<UserScriptMaster>,
// Returns the path to the directory user scripts are stored in.
FilePath user_script_dir() const { return user_script_dir_; }
- // Note: this is only for testing. This will reload the scripts associated
- // with the given extension. This is only temporary until we get better
- // machinery in place for toggling incognito-enabled extensions.
- void ReloadExtensionForTesting(Extension* extension);
-
protected:
friend class base::RefCountedThreadSafe<UserScriptMaster>;