172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_tabs_module.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <algorithm> 821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <vector> 921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/base64.h" 113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stringprintf.h" 143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_function_dispatcher.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_host.h" 1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h" 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_tabs_module_constants.h" 1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tabs/tab_strip_model.h" 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/translate/translate_tab_helper.h" 224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h" 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h" 244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser_navigator.h" 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_window.h" 2621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/window_sizer.h" 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/chrome_switches.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension.h" 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension_error_utils.h" 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/extensions/extension_messages.h" 3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/common/pref_names.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/url_constants.h" 34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/backing_store.h" 35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h" 36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host_delegate.h" 37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/navigation_entry.h" 38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/tab_contents/tab_contents_view.h" 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h" 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "skia/ext/image_operations.h" 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "skia/ext/platform_canvas.h" 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/skia/include/core/SkBitmap.h" 4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/codec/jpeg_codec.h" 4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/codec/png_codec.h" 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace keys = extension_tabs_module_constants; 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace errors = extension_manifest_errors; 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int CaptureVisibleTabFunction::kDefaultQuality = 90; 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Forward declare static helper functions defined below. 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |error_message| can optionally be passed in a will be set with an appropriate 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// message if the window cannot be found by id. 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic Browser* GetBrowserInProfileWithId(Profile* profile, 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int window_id, 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool include_incognito, 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string* error_message); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |error_message| can optionally be passed in and will be set with an 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// appropriate message if the tab cannot be found by id. 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool GetTabById(int tab_id, Profile* profile, 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool include_incognito, 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser** browser, 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel** tab_strip, 67201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper** contents, 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int* tab_index, std::string* error_message); 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Takes |url_string| and returns a GURL which is either valid and absolute 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// or invalid. If |url_string| is not directly interpretable as a valid (it is 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// likely a relative URL) an attempt is made to resolve it. |extension| is 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// provided so it can be resolved relative to its extension base 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// (chrome-extension://<id>/). Using the source frame url would be more correct, 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// but because the api shipped with urls resolved relative to their extension 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// base, we decided it wasn't worth breaking existing extensions to fix. 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic GURL ResolvePossiblyRelativeURL(const std::string& url_string, 78513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension); 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Return the type name for a browser window type. 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic std::string GetWindowTypeText(Browser::Type type); 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint ExtensionTabUtil::GetWindowId(const Browser* browser) { 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return browser->session_id().id(); 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint ExtensionTabUtil::GetTabId(const TabContents* tab_contents) { 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return tab_contents->controller().session_id().id(); 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string ExtensionTabUtil::GetTabStatusText(bool is_loading) { 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return is_loading ? keys::kStatusValueLoading : keys::kStatusValueComplete; 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint ExtensionTabUtil::GetWindowIdOfTab(const TabContents* tab_contents) { 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return tab_contents->controller().window_id().id(); 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDictionaryValue* ExtensionTabUtil::CreateTabValue( 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const TabContents* contents) { 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Find the tab strip and index of this guy. 102513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch TabStripModel* tab_strip = NULL; 103513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int tab_index; 104513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (ExtensionTabUtil::GetTabStripModel(contents, &tab_strip, &tab_index)) 105513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return ExtensionTabUtil::CreateTabValue(contents, tab_strip, tab_index); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Couldn't find it. This can happen if the tab is being dragged. 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ExtensionTabUtil::CreateTabValue(contents, NULL, -1); 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochListValue* ExtensionTabUtil::CreateTabList(const Browser* browser) { 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue* tab_list = new ListValue(); 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* tab_strip = browser->tabstrip_model(); 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < tab_strip->count(); ++i) { 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_list->Append(ExtensionTabUtil::CreateTabValue( 116201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch tab_strip->GetTabContentsAt(i)->tab_contents(), tab_strip, i)); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return tab_list; 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDictionaryValue* ExtensionTabUtil::CreateTabValue( 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const TabContents* contents, TabStripModel* tab_strip, int tab_index) { 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* result = new DictionaryValue(); 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetInteger(keys::kIdKey, ExtensionTabUtil::GetTabId(contents)); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetInteger(keys::kIndexKey, tab_index); 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetInteger(keys::kWindowIdKey, 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionTabUtil::GetWindowIdOfTab(contents)); 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetString(keys::kUrlKey, contents->GetURL().spec()); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetString(keys::kStatusKey, GetTabStatusText(contents->is_loading())); 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetBoolean(keys::kSelectedKey, 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_strip && tab_index == tab_strip->active_index()); 133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch result->SetBoolean(keys::kPinnedKey, 134513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch tab_strip && tab_strip->IsTabPinned(tab_index)); 1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick result->SetString(keys::kTitleKey, contents->GetTitle()); 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetBoolean(keys::kIncognitoKey, 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch contents->profile()->IsOffTheRecord()); 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!contents->is_loading()) { 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationEntry* entry = contents->controller().GetActiveEntry(); 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry) { 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry->favicon().is_valid()) 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen result->SetString(keys::kFaviconUrlKey, entry->favicon().url().spec()); 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// if |populate| is true, each window gets a list property |tabs| which contains 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// fully populated tab objects. 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDictionaryValue* ExtensionTabUtil::CreateWindowValue(const Browser* browser, 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool populate_tabs) { 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(browser); 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(browser->window()); 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* result = new DictionaryValue(); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetInteger(keys::kIdKey, ExtensionTabUtil::GetWindowId(browser)); 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetBoolean(keys::kIncognitoKey, 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->profile()->IsOffTheRecord()); 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetBoolean(keys::kFocusedKey, browser->window()->IsActive()); 16172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen gfx::Rect bounds; 16272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (browser->window()->IsMaximized() || browser->window()->IsFullscreen()) 16372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bounds = browser->window()->GetBounds(); 16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else 16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bounds = browser->window()->GetRestoredBounds(); 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetInteger(keys::kLeftKey, bounds.x()); 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetInteger(keys::kTopKey, bounds.y()); 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetInteger(keys::kWidthKey, bounds.width()); 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetInteger(keys::kHeightKey, bounds.height()); 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetString(keys::kWindowTypeKey, GetWindowTypeText(browser->type())); 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (populate_tabs) { 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->Set(keys::kTabsKey, ExtensionTabUtil::CreateTabList(browser)); 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 180513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ExtensionTabUtil::GetTabStripModel(const TabContents* tab_contents, 181513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch TabStripModel** tab_strip_model, 182513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int* tab_index) { 183513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(tab_contents); 184513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(tab_strip_model); 185513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(tab_index); 186513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 187513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (BrowserList::const_iterator it = BrowserList::begin(); 188513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch it != BrowserList::end(); ++it) { 189513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch TabStripModel* tab_strip = (*it)->tabstrip_model(); 190201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch int index = tab_strip->GetWrapperIndex(tab_contents); 191513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (index != -1) { 192513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch *tab_strip_model = tab_strip; 193513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch *tab_index = index; 194513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return true; 195513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 196513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 197513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 198513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 199513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 200513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 201201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool ExtensionTabUtil::GetDefaultTab(Browser* browser, 202201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper** contents, 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int* tab_id) { 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(browser); 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(contents); 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(tab_id); 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 208201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch *contents = browser->GetSelectedTabContentsWrapper(); 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (*contents) { 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_id) 211201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch *tab_id = ExtensionTabUtil::GetTabId((*contents)->tab_contents()); 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ExtensionTabUtil::GetTabById(int tab_id, Profile* profile, 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool include_incognito, 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser** browser, 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel** tab_strip, 222201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper** contents, 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int* tab_index) { 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* incognito_profile = 2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick include_incognito && profile->HasOffTheRecordProfile() ? 2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick profile->GetOffTheRecordProfile() : NULL; 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (BrowserList::const_iterator iter = BrowserList::begin(); 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch iter != BrowserList::end(); ++iter) { 229201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch Browser* target_browser = *iter; 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (target_browser->profile() == profile || 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch target_browser->profile() == incognito_profile) { 232201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabStripModel* target_tab_strip = target_browser->tabstrip_model(); 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < target_tab_strip->count(); ++i) { 234201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* target_contents = 235201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch target_tab_strip->GetTabContentsAt(i); 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (target_contents->controller().session_id().id() == tab_id) { 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (browser) 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *browser = target_browser; 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_strip) 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *tab_strip = target_tab_strip; 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (contents) 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *contents = target_contents; 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_index) 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *tab_index = i; 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Windows --------------------------------------------------------------------- 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetWindowFunction::RunImpl() { 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id; 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = GetBrowserInProfileWithId(profile(), window_id, 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), &error_); 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser || !browser->window()) { 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage( 2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick keys::kWindowNotFoundError, base::IntToString(window_id)); 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateWindowValue(browser, false)); 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetCurrentWindowFunction::RunImpl() { 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = GetCurrentBrowser(); 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser || !browser->window()) { 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoCurrentWindowError; 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateWindowValue(browser, false)); 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetLastFocusedWindowFunction::RunImpl() { 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = BrowserList::FindBrowserWithType( 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile(), Browser::TYPE_ANY, include_incognito()); 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser || !browser->window()) { 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoLastFocusedWindowError; 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateWindowValue(browser, false)); 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetAllWindowsFunction::RunImpl() { 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool populate_tabs = false; 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasOptionalArgument(0)) { 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* args; 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args)); 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kPopulateKey)) { 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(keys::kPopulateKey, 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &populate_tabs)); 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(new ListValue()); 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* incognito_profile = 3063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick include_incognito() && profile()->HasOffTheRecordProfile() ? 3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick profile()->GetOffTheRecordProfile() : NULL; 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (BrowserList::const_iterator browser = BrowserList::begin(); 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser != BrowserList::end(); ++browser) { 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only examine browsers in the current profile that have windows. 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (((*browser)->profile() == profile() || 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*browser)->profile() == incognito_profile) && 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*browser)->window()) { 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<ListValue*>(result_.get())-> 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Append(ExtensionTabUtil::CreateWindowValue(*browser, populate_tabs)); 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CreateWindowFunction::RunImpl() { 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* args = NULL; 324731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::vector<GURL> urls; 32521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen TabContentsWrapper* contents = NULL; 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasOptionalArgument(0)) 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args)); 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Look for optional url. 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args) { 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kUrlKey)) { 333731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Value* url_value; 334731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::vector<std::string> url_strings; 335731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick args->Get(keys::kUrlKey, &url_value); 336731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 337731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // First, get all the URLs the client wants to open. 338731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (url_value->IsType(Value::TYPE_STRING)) { 339731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string url_string; 340731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick url_value->GetAsString(&url_string); 341731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick url_strings.push_back(url_string); 342731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else if (url_value->IsType(Value::TYPE_LIST)) { 343731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const ListValue* url_list = static_cast<const ListValue*>(url_value); 344731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (size_t i = 0; i < url_list->GetSize(); ++i) { 345731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string url_string; 346731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick EXTENSION_FUNCTION_VALIDATE(url_list->GetString(i, &url_string)); 347731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick url_strings.push_back(url_string); 348731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 349731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 350731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 351731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Second, resolve, validate and convert them to GURLs. 352731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (std::vector<std::string>::iterator i = url_strings.begin(); 353731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick i != url_strings.end(); ++i) { 354731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick GURL url = ResolvePossiblyRelativeURL(*i, GetExtension()); 355731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!url.is_valid()) { 356731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick error_ = ExtensionErrorUtils::FormatErrorMessage( 357731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick keys::kInvalidUrlError, *i); 358731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return false; 359731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 360731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick urls.push_back(url); 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 365dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Don't let the extension crash the browser or renderers. 366dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GURL browser_crash(chrome::kAboutBrowserCrash); 367dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GURL renderer_crash(chrome::kAboutCrashURL); 368dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (std::find(urls.begin(), urls.end(), browser_crash) != urls.end() || 369dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::find(urls.begin(), urls.end(), renderer_crash) != urls.end()) { 370dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen error_ = keys::kNoCrashBrowserError; 371dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return false; 372dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 373dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 37421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Look for optional tab id. 37521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (args) { 37621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int tab_id; 37721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (args->HasKey(keys::kTabIdKey)) { 37821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kTabIdKey, &tab_id)); 37921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 38021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Find the tab and detach it from the original window. 38121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Browser* source_browser = NULL; 38221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen TabStripModel* source_tab_strip = NULL; 38321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int tab_index = -1; 38421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!GetTabById(tab_id, profile(), include_incognito(), 38521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen &source_browser, &source_tab_strip, &contents, 38621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen &tab_index, &error_)) 38721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 38821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen contents = source_tab_strip->DetachTabContentsAt(tab_index); 38921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!contents) { 39021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen error_ = ExtensionErrorUtils::FormatErrorMessage( 39121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen keys::kTabNotFoundError, base::IntToString(tab_id)); 39221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 39321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 39421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 39521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 39621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Try to position the new browser relative its originating browser window. 398731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gfx::Rect window_bounds; 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool maximized; 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The call offsets the bounds by kWindowTilePixels (defined in WindowSizer to 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // be 10) 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE(rafaelw): It's ok if GetCurrentBrowser() returns NULL here. 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // GetBrowserWindowBounds will default to saved "default" values for the app. 405731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick WindowSizer::GetBrowserWindowBounds(std::string(), gfx::Rect(), 406731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick GetCurrentBrowser(), &window_bounds, 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &maximized); 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 409731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Calculate popup bounds separately. In ChromiumOS the default is 0x0 which 410731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // indicates default window sizes in PanelBrowserView. In other OSs popups 411731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // use the same default bounds as windows. 412731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gfx::Rect popup_bounds; 413731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#if !defined(OS_CHROMEOS) 414731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick popup_bounds = window_bounds; // Use window size as default for popups 415731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#endif 416731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* window_profile = profile(); 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser::Type window_type = Browser::TYPE_NORMAL; 419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool focused = true; 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args) { 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Any part of the bounds can optionally be set by the caller. 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int bounds_val; 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kLeftKey)) { 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kLeftKey, 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &bounds_val)); 427731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick window_bounds.set_x(bounds_val); 428731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick popup_bounds.set_x(bounds_val); 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kTopKey)) { 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kTopKey, 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &bounds_val)); 434731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick window_bounds.set_y(bounds_val); 435731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick popup_bounds.set_y(bounds_val); 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kWidthKey)) { 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kWidthKey, 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &bounds_val)); 441731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick window_bounds.set_width(bounds_val); 442731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick popup_bounds.set_width(bounds_val); 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kHeightKey)) { 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kHeightKey, 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &bounds_val)); 448731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick window_bounds.set_height(bounds_val); 449731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick popup_bounds.set_height(bounds_val); 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool incognito = false; 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kIncognitoKey)) { 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(keys::kIncognitoKey, 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &incognito)); 45672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!profile_->GetPrefs()->GetBoolean(prefs::kIncognitoEnabled)) { 45772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen error_ = keys::kIncognitoModeIsDisabled; 45872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 45972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 46072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (incognito) 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_profile = window_profile->GetOffTheRecordProfile(); 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 465ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (args->HasKey(keys::kFocusedKey)) 466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(keys::kFocusedKey, 467ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &focused)); 468ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string type_str; 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kWindowTypeKey)) { 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetString(keys::kWindowTypeKey, 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &type_str)); 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type_str == keys::kWindowTypeValueNormal) { 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_type = Browser::TYPE_NORMAL; 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (type_str == keys::kWindowTypeValuePopup) { 476731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick window_type = Browser::TYPE_APP_POPUP; 477ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (type_str == keys::kWindowTypeValuePanel) { 478ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (GetExtension()->HasApiPermission( 479ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Extension::kExperimentalPermission)) { 480ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen window_type = Browser::TYPE_APP_PANEL; 481ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 482ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen error_ = errors::kExperimentalFeature; 483ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 484ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(false); 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 491731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Browser* new_window = Browser::CreateForType(window_type, window_profile); 492513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (std::vector<GURL>::iterator i = urls.begin(); i != urls.end(); ++i) 493513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch new_window->AddSelectedTabWithURL(*i, PageTransition::LINK); 49421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (contents) { 49521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen TabStripModel* target_tab_strip = new_window->tabstrip_model(); 49621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen target_tab_strip->InsertTabContentsAt(urls.size(), contents, 49721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen TabStripModel::ADD_NONE); 498dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else if (urls.empty()) { 499731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new_window->NewTab(); 50021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 501731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new_window->SelectNumberedTab(0); 502731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (window_type & Browser::TYPE_POPUP) 503731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new_window->window()->SetBounds(popup_bounds); 504731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick else 505731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new_window->window()->SetBounds(window_bounds); 506ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 507ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (focused) 508ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new_window->window()->Show(); 509ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen else 510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new_window->window()->ShowInactive(); 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_window->profile()->IsOffTheRecord() && !include_incognito()) { 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't expose incognito windows if the extension isn't allowed. 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(Value::CreateNullValue()); 515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 516731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick result_.reset(ExtensionTabUtil::CreateWindowValue(new_window, true)); 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool UpdateWindowFunction::RunImpl() { 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id; 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* update_props; 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props)); 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = GetBrowserInProfileWithId(profile(), window_id, 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), &error_); 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser || !browser->window()) { 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage( 5323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick keys::kWindowNotFoundError, base::IntToString(window_id)); 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect bounds = browser->window()->GetRestoredBounds(); 53772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool set_bounds = false; 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Any part of the bounds can optionally be set by the caller. 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int bounds_val; 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (update_props->HasKey(keys::kLeftKey)) { 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kLeftKey, 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &bounds_val)); 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds.set_x(bounds_val); 54572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set_bounds = true; 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (update_props->HasKey(keys::kTopKey)) { 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kTopKey, 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &bounds_val)); 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds.set_y(bounds_val); 55372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set_bounds = true; 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (update_props->HasKey(keys::kWidthKey)) { 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kWidthKey, 559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &bounds_val)); 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds.set_width(bounds_val); 56172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set_bounds = true; 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (update_props->HasKey(keys::kHeightKey)) { 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kHeightKey, 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &bounds_val)); 568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds.set_height(bounds_val); 56972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set_bounds = true; 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 57172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (set_bounds) 57272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen browser->window()->SetBounds(bounds); 573731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 574731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick bool selected_val = false; 575731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (update_props->HasKey(keys::kFocusedKey)) { 576731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( 577731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick keys::kFocusedKey, &selected_val)); 578731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (selected_val) 579731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick browser->window()->Activate(); 580731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick else 581731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick browser->window()->Deactivate(); 582731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 583731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateWindowValue(browser, false)); 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool RemoveWindowFunction::RunImpl() { 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id; 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); 592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = GetBrowserInProfileWithId(profile(), window_id, 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), &error_); 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) 596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 59821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Don't let the extension remove the window if the user is dragging tabs 59921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // in that window. 60021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!browser->IsTabStripEditable()) { 60121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen error_ = keys::kTabStripNotEditableError; 60221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 60321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 60421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->CloseWindow(); 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tabs ------------------------------------------------------------------------ 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetSelectedTabFunction::RunImpl() { 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser; 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // windowId defaults to "current" window. 615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id = -1; 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasOptionalArgument(0)) { 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetBrowserInProfileWithId(profile(), window_id, 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), &error_); 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetCurrentBrowser(); 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) 624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoCurrentWindowError; 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* tab_strip = browser->tabstrip_model(); 630201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* contents = tab_strip->GetSelectedTabContents(); 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!contents) { 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoSelectedTabError; 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 635201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch result_.reset(ExtensionTabUtil::CreateTabValue(contents->tab_contents(), 636201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch tab_strip, 637ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_strip->active_index())); 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetAllTabsInWindowFunction::RunImpl() { 642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser; 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // windowId defaults to "current" window. 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id = -1; 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasOptionalArgument(0)) { 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetBrowserInProfileWithId(profile(), window_id, 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), &error_); 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetCurrentBrowser(); 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoCurrentWindowError; 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateTabList(browser)); 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CreateTabFunction::RunImpl() { 663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* args; 664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args)); 665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser *browser; 667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // windowId defaults to "current" window. 668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id = -1; 669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kWindowIdKey)) { 670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetInteger( 671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kWindowIdKey, &window_id)); 672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetBrowserInProfileWithId(profile(), window_id, 673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), &error_); 674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetCurrentBrowser(); 676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) 677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoCurrentWindowError; 678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) 680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(rafaelw): handle setting remaining tab properties: 683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // -title 684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // -favIconUrl 685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string url_string; 687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url; 688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kUrlKey)) { 689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetString(keys::kUrlKey, 690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &url_string)); 691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url = ResolvePossiblyRelativeURL(url_string, GetExtension()); 692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url.is_valid()) { 693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_string); 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 699dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Don't let extensions crash the browser or renderers. 700dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (url == GURL(chrome::kAboutBrowserCrash) || 701dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen url == GURL(chrome::kAboutCrashURL)) { 702dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen error_ = keys::kNoCrashBrowserError; 703dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return false; 704dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 705dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Default to foreground for the new tab. The presence of 'selected' property 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // will override this default. 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool selected = true; 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kSelectedKey)) 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(keys::kSelectedKey, 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &selected)); 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 713513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Default to not pinning the tab. Setting the 'pinned' property to true 714513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // will override this default. 715513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool pinned = false; 716513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (args->HasKey(keys::kPinnedKey)) 717513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(keys::kPinnedKey, &pinned)); 718513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 719513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // We can't load extension URLs into incognito windows unless the extension 720513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // uses split mode. Special case to fall back to a normal window. 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url.SchemeIs(chrome::kExtensionScheme) && 722513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch !GetExtension()->incognito_split_mode() && 723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->profile()->IsOffTheRecord()) { 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* profile = browser->profile()->GetOriginalProfile(); 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = BrowserList::FindBrowserWithType(profile, 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser::TYPE_NORMAL, false); 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) { 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = Browser::Create(profile); 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->window()->Show(); 730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 733731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If index is specified, honor the value, but keep it bound to 734731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // -1 <= index <= tab_strip->count() where -1 invokes the default behavior. 735731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int index = -1; 736731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (args->HasKey(keys::kIndexKey)) 737731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kIndexKey, &index)); 738731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* tab_strip = browser->tabstrip_model(); 740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 741731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick index = std::min(std::max(index, -1), tab_strip->count()); 742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 743ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int add_types = selected ? TabStripModel::ADD_ACTIVE : 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel::ADD_NONE; 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch add_types |= TabStripModel::ADD_FORCE_INDEX; 746513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (pinned) 747513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch add_types |= TabStripModel::ADD_PINNED; 748513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch browser::NavigateParams params(browser, url, PageTransition::LINK); 749513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch params.disposition = selected ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB; 750513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch params.tabstrip_index = index; 751513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch params.tabstrip_add_types = add_types; 752513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch browser::Navigate(¶ms); 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (selected) 755513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch params.target_contents->view()->SetInitialFocus(); 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Return data about the newly created tab. 758513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (has_callback()) { 759513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch result_.reset(ExtensionTabUtil::CreateTabValue( 760201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch params.target_contents->tab_contents(), 761513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch params.browser->tabstrip_model(), 762513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch params.browser->tabstrip_model()->GetIndexOfTabContents( 763513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch params.target_contents))); 764513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetTabFunction::RunImpl() { 770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id; 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id)); 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* tab_strip = NULL; 774201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* contents = NULL; 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_index = -1; 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetTabById(tab_id, profile(), include_incognito(), 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL, &tab_strip, &contents, &tab_index, &error_)) 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 780201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch result_.reset(ExtensionTabUtil::CreateTabValue(contents->tab_contents(), 781201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch tab_strip, 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_index)); 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetCurrentTabFunction::RunImpl() { 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(dispatcher()); 788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = dispatcher()->delegate()->associated_tab_contents(); 790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (contents) 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateTabValue(contents)); 792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 796ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenUpdateTabFunction::UpdateTabFunction() 797ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : ALLOW_THIS_IN_INITIALIZER_LIST(registrar_(this)) { 798ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 799ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool UpdateTabFunction::RunImpl() { 801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id; 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id)); 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* update_props; 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props)); 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* tab_strip = NULL; 807201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* contents = NULL; 808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_index = -1; 809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetTabById(tab_id, profile(), include_incognito(), 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL, &tab_strip, &contents, &tab_index, &error_)) 811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationController& controller = contents->controller(); 814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(rafaelw): handle setting remaining tab properties: 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // -title 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // -favIconUrl 818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Navigate the tab to a new location if the url different. 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string url_string; 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (update_props->HasKey(keys::kUrlKey)) { 822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetString( 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kUrlKey, &url_string)); 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url = ResolvePossiblyRelativeURL(url_string, GetExtension()); 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url.is_valid()) { 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_string); 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 832dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Don't let the extension crash the browser or renderers. 833dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (url == GURL(chrome::kAboutBrowserCrash) || 834dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen url == GURL(chrome::kAboutCrashURL)) { 835dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen error_ = keys::kNoCrashBrowserError; 836dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return false; 837dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 838dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // JavaScript URLs can do the same kinds of things as cross-origin XHR, so 840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we need to check host permissions before allowing them. 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url.SchemeIs(chrome::kJavaScriptScheme)) { 84272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!GetExtension()->CanExecuteScriptOnPage( 84372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen contents->tab_contents()->GetURL(), NULL, &error_)) { 844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 845731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 847ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExtensionMsg_ExecuteCode_Params params; 848ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen params.request_id = request_id(); 849ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen params.extension_id = extension_id(); 850ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen params.is_javascript = true; 851ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen params.code = url.path(); 852ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen params.all_frames = false; 853ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen params.in_main_world = true; 854ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 855ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RenderViewHost* render_view_host = 856ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen contents->tab_contents()->render_view_host(); 857ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen render_view_host->Send( 858ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new ExtensionMsg_ExecuteCode(render_view_host->routing_id(), 859ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen params)); 860ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 861ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen registrar_.Observe(contents->tab_contents()); 862ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen AddRef(); // balanced in Observe() 863ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 864ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller.LoadURL(url, GURL(), PageTransition::LINK); 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The URL of a tab contents never actually changes to a JavaScript URL, so 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this check only makes sense in other cases. 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url.SchemeIs(chrome::kJavaScriptScheme)) 872201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK_EQ(url.spec(), contents->tab_contents()->GetURL().spec()); 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool selected = false; 876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(rafaelw): Setting |selected| from js doesn't make much sense. 877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Move tab selection management up to window. 878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (update_props->HasKey(keys::kSelectedKey)) { 879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( 880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kSelectedKey, 881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &selected)); 882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (selected) { 883ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (tab_strip->active_index() != tab_index) { 884ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_strip->ActivateTabAt(tab_index, false); 885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(contents, tab_strip->GetSelectedTabContents()); 886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 887201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch contents->tab_contents()->Focus(); 888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 891513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool pinned = false; 892513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (update_props->HasKey(keys::kPinnedKey)) { 893513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean(keys::kPinnedKey, 894513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch &pinned)); 895513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch tab_strip->SetTabPinned(tab_index, pinned); 896513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 897513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Update the tab index because it may move when being pinned. 898513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch tab_index = tab_strip->GetIndexOfTabContents(contents); 899513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 900513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (has_callback()) 902201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch result_.reset(ExtensionTabUtil::CreateTabValue(contents->tab_contents(), 903201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch tab_strip, 904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_index)); 905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 906ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SendResponse(true); 907ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 908ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 909ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 910ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool UpdateTabFunction::OnMessageReceived(const IPC::Message& message) { 911ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (message.type() != ExtensionHostMsg_ExecuteCodeFinished::ID) 912ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 913ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 914ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int message_request_id; 915ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void* iter = NULL; 916ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!message.ReadInt(&iter, &message_request_id)) { 917ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED() << "malformed extension message"; 918ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 919ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 920ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 921ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (message_request_id != request_id()) 922ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 923ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 924ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IPC_BEGIN_MESSAGE_MAP(UpdateTabFunction, message) 925ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IPC_MESSAGE_HANDLER(ExtensionHostMsg_ExecuteCodeFinished, 926ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnExecuteCodeFinished) 927ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IPC_END_MESSAGE_MAP() 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 931ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid UpdateTabFunction::OnExecuteCodeFinished(int request_id, 932ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool success, 933ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& error) { 934ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!error.empty()) { 935ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CHECK(!success); 936ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen error_ = error; 937ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 938ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 939ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SendResponse(success); 940ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 941ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen registrar_.Observe(NULL); 942ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Release(); // balanced in Execute() 943ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 944ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool MoveTabFunction::RunImpl() { 946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id; 947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id)); 948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* update_props; 949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props)); 950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int new_index; 952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( 953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kIndexKey, &new_index)); 954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(new_index >= 0); 955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* source_browser = NULL; 957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* source_tab_strip = NULL; 958201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* contents = NULL; 959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_index = -1; 960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetTabById(tab_id, profile(), include_incognito(), 961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &source_browser, &source_tab_strip, &contents, 962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &tab_index, &error_)) 963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 96521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Don't let the extension move the tab if the user is dragging tabs. 96621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!source_browser->IsTabStripEditable()) { 96721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen error_ = keys::kTabStripNotEditableError; 968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (update_props->HasKey(keys::kWindowIdKey)) { 972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* target_browser; 973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id; 974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( 975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kWindowIdKey, &window_id)); 976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch target_browser = GetBrowserInProfileWithId(profile(), window_id, 977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), &error_); 978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!target_browser) 979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 98121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!target_browser->IsTabStripEditable()) { 98221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen error_ = keys::kTabStripNotEditableError; 98321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 98421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 98521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (target_browser->type() != Browser::TYPE_NORMAL) { 987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kCanOnlyMoveTabsWithinNormalWindowsError; 988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 99172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (target_browser->profile() != source_browser->profile()) { 99272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen error_ = keys::kCanOnlyMoveTabsWithinSameProfileError; 99372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 99472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 99572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If windowId is different from the current window, move between windows. 997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ExtensionTabUtil::GetWindowId(target_browser) != 998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionTabUtil::GetWindowId(source_browser)) { 999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* target_tab_strip = target_browser->tabstrip_model(); 1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch contents = source_tab_strip->DetachTabContentsAt(tab_index); 1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!contents) { 1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage( 10033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick keys::kTabNotFoundError, base::IntToString(tab_id)); 1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Clamp move location to the last position. 1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is ">" because it can append to a new index position. 1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_index > target_tab_strip->count()) 1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_index = target_tab_strip->count(); 1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch target_tab_strip->InsertTabContentsAt(new_index, contents, 1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel::ADD_NONE); 1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (has_callback()) 1016201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch result_.reset(ExtensionTabUtil::CreateTabValue(contents->tab_contents(), 1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch target_tab_strip, new_index)); 1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Perform a simple within-window move. 1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Clamp move location to the last position. 1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is ">=" because the move must be to an existing location. 1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_index >= source_tab_strip->count()) 1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_index = source_tab_strip->count() - 1; 1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_index != tab_index) 1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch source_tab_strip->MoveTabContentsAt(tab_index, new_index, false); 1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (has_callback()) 1033201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch result_.reset(ExtensionTabUtil::CreateTabValue(contents->tab_contents(), 1034ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_tab_strip, 1035ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new_index)); 1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool RemoveTabFunction::RunImpl() { 1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id; 1042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id)); 1043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = NULL; 1045201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* contents = NULL; 1046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetTabById(tab_id, profile(), include_incognito(), 1047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &browser, NULL, &contents, NULL, &error_)) 1048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 105021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Don't let the extension remove a tab if the user is dragging tabs around. 105121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!browser->IsTabStripEditable()) { 105221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen error_ = keys::kTabStripNotEditableError; 105321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 105421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 105521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Close the tab in this convoluted way, since there's a chance that the tab 1057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is being dragged, or we're in some other nested event loop. This code path 1058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // should ensure that the tab is safely closed under such circumstances, 1059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // whereas |Browser::CloseTabContents()| does not. 1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RenderViewHost* render_view_host = contents->render_view_host(); 1061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch render_view_host->delegate()->Close(render_view_host); 1062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1064c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CaptureVisibleTabFunction::RunImpl() { 1066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser; 1067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // windowId defaults to "current" window. 1068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id = -1; 1069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasOptionalArgument(0)) { 1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); 1072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetBrowserInProfileWithId(profile(), window_id, 1073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), &error_); 1074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetCurrentBrowser(); 1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) { 1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoCurrentWindowError; 1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch image_format_ = FORMAT_JPEG; // Default format is JPEG. 1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch image_quality_ = kDefaultQuality; // Default quality setting. 1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasOptionalArgument(1)) { 1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* options; 1088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &options)); 1089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (options->HasKey(keys::kFormatKey)) { 1091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string format; 1092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE( 1093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options->GetString(keys::kFormatKey, &format)); 1094c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (format == keys::kFormatValueJpeg) { 1096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch image_format_ = FORMAT_JPEG; 1097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (format == keys::kFormatValuePng) { 1098c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch image_format_ = FORMAT_PNG; 1099c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Schema validation should make this unreachable. 1101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(0); 1102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (options->HasKey(keys::kQualityKey)) { 1106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE( 1107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options->GetInteger(keys::kQualityKey, &image_quality_)); 1108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* tab_contents = browser->GetSelectedTabContents(); 1112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!tab_contents) { 1113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kInternalVisibleTabCaptureError; 1114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // captureVisibleTab() can return an image containing sensitive information 1118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // that the browser would otherwise protect. Ensure the extension has 1119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // permission to do this. 1120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!GetExtension()->CanCaptureVisiblePage(tab_contents->GetURL(), &error_)) 1121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return false; 1122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RenderViewHost* render_view_host = tab_contents->render_view_host(); 1124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If a backing store is cached for the tab we want to capture, 1126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and it can be copied into a bitmap, then use it to generate the image. 1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BackingStore* backing_store = render_view_host->GetBackingStore(false); 1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (backing_store && CaptureSnapshotFromBackingStore(backing_store)) 1129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ask the renderer for a snapshot of the tab. 1132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch render_view_host->CaptureSnapshot(); 1133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, 1134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType::TAB_SNAPSHOT_TAKEN, 1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 1136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddRef(); // Balanced in CaptureVisibleTabFunction::Observe(). 1137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Build the image of a tab's contents out of a backing store. 1142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This may fail if we can not copy a backing store into a bitmap. 1143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// For example, some uncommon X11 visual modes are not supported by 1144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// CopyFromBackingStore(). 1145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CaptureVisibleTabFunction::CaptureSnapshotFromBackingStore( 1146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BackingStore* backing_store) { 1147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch skia::PlatformCanvas temp_canvas; 1149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!backing_store->CopyFromBackingStore(gfx::Rect(backing_store->size()), 1150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &temp_canvas)) { 1151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1153513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "captureVisibleTab() got image from backing store."; 1154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResultFromBitmap( 1156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch temp_canvas.getTopPlatformDevice().accessBitmap(false)); 1157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// If a backing store was not available in CaptureVisibleTabFunction::RunImpl, 1161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// than the renderer was asked for a snapshot. Listen for a notification 1162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// that the snapshot is available. 1163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CaptureVisibleTabFunction::Observe(NotificationType type, 1164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 1165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 1166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(type == NotificationType::TAB_SNAPSHOT_TAKEN); 1167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap *screen_capture = Details<const SkBitmap>(details).ptr(); 1169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool error = screen_capture->empty(); 1170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (error) { 1172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kInternalVisibleTabCaptureError; 1173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResponse(false); 1174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1175513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "captureVisibleTab() got image from renderer."; 1176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResultFromBitmap(*screen_capture); 1177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Release(); // Balanced in CaptureVisibleTabFunction::RunImpl(). 1180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Turn a bitmap of the screen into an image, set that image as the result, 1183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// and call SendResponse(). 1184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CaptureVisibleTabFunction::SendResultFromBitmap( 1185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap& screen_capture) { 1186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<RefCountedBytes> image_data(new RefCountedBytes); 1187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkAutoLockPixels screen_capture_lock(screen_capture); 1188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool encoded = false; 1189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string mime_type; 1190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (image_format_) { 1191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case FORMAT_JPEG: 1192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch encoded = gfx::JPEGCodec::Encode( 1193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<unsigned char*>(screen_capture.getAddr32(0, 0)), 1194731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gfx::JPEGCodec::FORMAT_SkBitmap, 1195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_capture.width(), 1196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_capture.height(), 1197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(screen_capture.rowBytes()), 1198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch image_quality_, 1199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &image_data->data); 1200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mime_type = keys::kMimeTypeJpeg; 1201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case FORMAT_PNG: 1203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch encoded = gfx::PNGCodec::EncodeBGRASkBitmap( 1204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_capture, 1205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch true, // Discard transparency. 1206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &image_data->data); 1207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mime_type = keys::kMimeTypePng; 1208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 1210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED() << "Invalid image format."; 1211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!encoded) { 1214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage( 1215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kInternalVisibleTabCaptureError, ""); 1216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResponse(false); 1217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string base64_result; 1221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string stream_as_string; 1222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_as_string.resize(image_data->data.size()); 1223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(&stream_as_string[0], 1224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<const char*>(&image_data->data[0]), 1225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch image_data->data.size()); 1226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Base64Encode(stream_as_string, &base64_result); 12283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base64_result.insert(0, base::StringPrintf("data:%s;base64,", 12293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick mime_type.c_str())); 1230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(new StringValue(base64_result)); 1231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResponse(true); 1232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DetectTabLanguageFunction::RunImpl() { 1235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id = 0; 1236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = NULL; 1237201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* contents = NULL; 1238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If |tab_id| is specified, look for it. Otherwise default to selected tab 1240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in the current window. 1241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasOptionalArgument(0)) { 1242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id)); 1243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetTabById(tab_id, profile(), include_incognito(), 1244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &browser, NULL, &contents, NULL, &error_)) { 1245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser || !contents) 1248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetCurrentBrowser(); 1251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) 1252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch contents = browser->tabstrip_model()->GetSelectedTabContents(); 1254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!contents) 1255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (contents->controller().needs_reload()) { 1259731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If the tab hasn't been loaded, don't wait for the tab to load. 1260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kCannotDetermineLanguageOfUnloadedTab; 1261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddRef(); // Balanced in GotLanguage() 1265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TranslateTabHelper* helper = contents->translate_tab_helper(); 1267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!helper->language_state().original_language().empty()) { 1268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Delay the callback invocation until after the current JS call has 1269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // returned. 1270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 1271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this, &DetectTabLanguageFunction::GotLanguage, 1272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen helper->language_state().original_language())); 1273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The tab contents does not know its language yet. Let's wait until it 1276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // receives it, or until the tab is closed/navigates to some other page. 1277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::TAB_LANGUAGE_DETERMINED, 1278201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch Source<TabContents>(contents->tab_contents())); 1279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::TAB_CLOSING, 1280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<NavigationController>(&(contents->controller()))); 1281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, 1282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<NavigationController>(&(contents->controller()))); 1283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DetectTabLanguageFunction::Observe(NotificationType type, 1287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 1288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 1289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string language; 1290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type == NotificationType::TAB_LANGUAGE_DETERMINED) 1291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch language = *Details<std::string>(details).ptr(); 1292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.RemoveAll(); 1294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Call GotLanguage in all cases as we want to guarantee the callback is 1296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // called for every API call the extension made. 1297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GotLanguage(language); 1298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DetectTabLanguageFunction::GotLanguage(const std::string& language) { 1301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(Value::CreateStringValue(language.c_str())); 1302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResponse(true); 1303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Release(); // Balanced in Run() 1305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static helpers 1308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// TODO(jhawkins): Move these to unnamed namespace and remove static modifier. 1309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic Browser* GetBrowserInProfileWithId(Profile* profile, 1311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int window_id, 1312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool include_incognito, 1313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string* error_message) { 1314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* incognito_profile = 13153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick include_incognito && profile->HasOffTheRecordProfile() ? 13163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick profile->GetOffTheRecordProfile() : NULL; 1317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (BrowserList::const_iterator browser = BrowserList::begin(); 1318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser != BrowserList::end(); ++browser) { 1319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (((*browser)->profile() == profile || 1320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*browser)->profile() == incognito_profile) && 1321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionTabUtil::GetWindowId(*browser) == window_id) 1322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return *browser; 1323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (error_message) 1326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *error_message = ExtensionErrorUtils::FormatErrorMessage( 13273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick keys::kWindowNotFoundError, base::IntToString(window_id)); 1328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 1330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool GetTabById(int tab_id, Profile* profile, 1333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool include_incognito, 1334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser** browser, 1335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel** tab_strip, 1336201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper** contents, 1337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int* tab_index, 1338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string* error_message) { 1339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ExtensionTabUtil::GetTabById(tab_id, profile, include_incognito, 1340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser, tab_strip, contents, tab_index)) 1341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (error_message) 1344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *error_message = ExtensionErrorUtils::FormatErrorMessage( 13453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick keys::kTabNotFoundError, base::IntToString(tab_id)); 1346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic std::string GetWindowTypeText(Browser::Type type) { 1351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (type == Browser::TYPE_APP_PANEL && 1352ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CommandLine::ForCurrentProcess()->HasSwitch( 1353ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen switches::kEnableExperimentalExtensionApis)) 1354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return keys::kWindowTypeValuePanel; 1355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1356731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if ((type & Browser::TYPE_POPUP) == Browser::TYPE_POPUP) 1357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return keys::kWindowTypeValuePopup; 1358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1359731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if ((type & Browser::TYPE_APP) == Browser::TYPE_APP) 1360731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return keys::kWindowTypeValueApp; 1361731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(type == Browser::TYPE_NORMAL); 1363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return keys::kWindowTypeValueNormal; 1364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic GURL ResolvePossiblyRelativeURL(const std::string& url_string, 1367513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension) { 1368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url = GURL(url_string); 1369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url.is_valid()) 1370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url = extension->GetResourceURL(url_string); 1371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return url; 1373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1374