Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(289)

Side by Side Diff: chrome/browser/extensions/extension_tabs_module.cc

Issue 9234042: Re-land alexbost's experimental offscreenTabs API. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: merge / rebase Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/extension_tabs_module.h" 5 #include "chrome/browser/extensions/extension_tabs_module.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/base64.h" 10 #include "base/base64.h"
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 #include "ui/gfx/codec/png_codec.h" 60 #include "ui/gfx/codec/png_codec.h"
61 61
62 namespace keys = extension_tabs_module_constants; 62 namespace keys = extension_tabs_module_constants;
63 namespace errors = extension_manifest_errors; 63 namespace errors = extension_manifest_errors;
64 64
65 using content::NavigationController; 65 using content::NavigationController;
66 using content::NavigationEntry; 66 using content::NavigationEntry;
67 using content::OpenURLParams; 67 using content::OpenURLParams;
68 using content::Referrer; 68 using content::Referrer;
69 using content::WebContents; 69 using content::WebContents;
70 using extensions::tabs_module::IsCrashURL;
71 using extensions::tabs_module::ResolvePossiblyRelativeURL;
70 72
71 const int CaptureVisibleTabFunction::kDefaultQuality = 90; 73 const int CaptureVisibleTabFunction::kDefaultQuality = 90;
72 74
73 namespace { 75 namespace {
74 76
75 // |error_message| can optionally be passed in a will be set with an appropriate 77 // |error_message| can optionally be passed in a will be set with an appropriate
76 // message if the window cannot be found by id. 78 // message if the window cannot be found by id.
77 Browser* GetBrowserInProfileWithId(Profile* profile, 79 Browser* GetBrowserInProfileWithId(Profile* profile,
78 const int window_id, 80 const int window_id,
79 bool include_incognito, 81 bool include_incognito,
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 browser, tab_strip, contents, tab_index)) 133 browser, tab_strip, contents, tab_index))
132 return true; 134 return true;
133 135
134 if (error_message) 136 if (error_message)
135 *error_message = ExtensionErrorUtils::FormatErrorMessage( 137 *error_message = ExtensionErrorUtils::FormatErrorMessage(
136 keys::kTabNotFoundError, base::IntToString(tab_id)); 138 keys::kTabNotFoundError, base::IntToString(tab_id));
137 139
138 return false; 140 return false;
139 } 141 }
140 142
141 // Takes |url_string| and returns a GURL which is either valid and absolute
142 // or invalid. If |url_string| is not directly interpretable as a valid (it is
143 // likely a relative URL) an attempt is made to resolve it. |extension| is
144 // provided so it can be resolved relative to its extension base
145 // (chrome-extension://<id>/). Using the source frame url would be more correct,
146 // but because the api shipped with urls resolved relative to their extension
147 // base, we decided it wasn't worth breaking existing extensions to fix.
148 GURL ResolvePossiblyRelativeURL(const std::string& url_string,
149 const Extension* extension) {
150 GURL url = GURL(url_string);
151 if (!url.is_valid())
152 url = extension->GetResourceURL(url_string);
153
154 return url;
155 }
156
157 bool IsCrashURL(const GURL& url) {
158 // Check a fixed-up URL, to normalize the scheme and parse hosts correctly.
159 GURL fixed_url =
160 URLFixerUpper::FixupURL(url.possibly_invalid_spec(), std::string());
161 return (fixed_url.SchemeIs(chrome::kChromeUIScheme) &&
162 (fixed_url.host() == chrome::kChromeUIBrowserCrashHost ||
163 fixed_url.host() == chrome::kChromeUICrashHost));
164 }
165
166 // Reads the |value| as either a single integer value or a list of integers. 143 // Reads the |value| as either a single integer value or a list of integers.
167 bool ReadOneOrMoreIntegers( 144 bool ReadOneOrMoreIntegers(
168 Value* value, std::vector<int>* result) { 145 Value* value, std::vector<int>* result) {
169 if (value->IsType(Value::TYPE_INTEGER)) { 146 if (value->IsType(Value::TYPE_INTEGER)) {
170 int tab_id = -1; 147 int tab_id = -1;
171 if (!value->GetAsInteger(&tab_id)) 148 if (!value->GetAsInteger(&tab_id))
172 return false; 149 return false;
173 result->push_back(tab_id); 150 result->push_back(tab_id);
174 return true; 151 return true;
175 152
(...skipping 29 matching lines...) Expand all
205 if (query->HasKey(key)) { 182 if (query->HasKey(key)) {
206 bool value = false; 183 bool value = false;
207 CHECK(query->GetBoolean(key, &value)); 184 CHECK(query->GetBoolean(key, &value));
208 return value ? MATCH_TRUE : MATCH_FALSE; 185 return value ? MATCH_TRUE : MATCH_FALSE;
209 } 186 }
210 return NOT_SET; 187 return NOT_SET;
211 } 188 }
212 189
213 } // namespace 190 } // namespace
214 191
192 namespace extensions {
193 namespace tabs_module {
194
195 GURL ResolvePossiblyRelativeURL(const std::string& url_string,
196 const Extension* extension) {
197 GURL url = GURL(url_string);
198 if (!url.is_valid())
199 url = extension->GetResourceURL(url_string);
200
201 return url;
202 }
203
204 bool IsCrashURL(const GURL& url) {
205 // Check a fixed-up URL, to normalize the scheme and parse hosts correctly.
206 GURL fixed_url =
207 URLFixerUpper::FixupURL(url.possibly_invalid_spec(), std::string());
208 return (fixed_url.SchemeIs(chrome::kChromeUIScheme) &&
209 (fixed_url.host() == chrome::kChromeUIBrowserCrashHost ||
210 fixed_url.host() == chrome::kChromeUICrashHost));
211 }
212
213 } // namespace tabs_module
214 } // namespace extensions
215
215 // Windows --------------------------------------------------------------------- 216 // Windows ---------------------------------------------------------------------
216 217
217 bool GetWindowFunction::RunImpl() { 218 bool GetWindowFunction::RunImpl() {
218 int window_id = extension_misc::kUnknownWindowId; 219 int window_id = extension_misc::kUnknownWindowId;
219 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); 220 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id));
220 221
221 bool populate_tabs = false; 222 bool populate_tabs = false;
222 if (HasOptionalArgument(1)) { 223 if (HasOptionalArgument(1)) {
223 DictionaryValue* args = NULL; 224 DictionaryValue* args = NULL;
224 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &args)); 225 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &args));
(...skipping 864 matching lines...) Expand 10 before | Expand all | Expand 10 after
1089 } 1090 }
1090 1091
1091 int tab_index = -1; 1092 int tab_index = -1;
1092 TabStripModel* tab_strip = NULL; 1093 TabStripModel* tab_strip = NULL;
1093 if (!GetTabById(tab_id, profile(), include_incognito(), 1094 if (!GetTabById(tab_id, profile(), include_incognito(),
1094 NULL, &tab_strip, &contents, &tab_index, &error_)) { 1095 NULL, &tab_strip, &contents, &tab_index, &error_)) {
1095 return false; 1096 return false;
1096 } 1097 }
1097 1098
1098 web_contents_ = contents->web_contents(); 1099 web_contents_ = contents->web_contents();
1099 NavigationController& controller = web_contents_->GetController();
1100 1100
1101 // TODO(rafaelw): handle setting remaining tab properties: 1101 // TODO(rafaelw): handle setting remaining tab properties:
1102 // -title 1102 // -title
1103 // -favIconUrl 1103 // -favIconUrl
1104 1104
1105 // We wait to fire the callback when executing 'javascript:' URLs in tabs. 1105 // Navigate the tab to a new location if the url is different.
1106 bool is_async = false; 1106 bool is_async = false;
1107 1107 if (!UpdateURLIfPresent(update_props, &is_async))
1108 // Navigate the tab to a new location if the url is different. 1108 return false;
1109 std::string url_string;
1110 if (update_props->HasKey(keys::kUrlKey)) {
1111 EXTENSION_FUNCTION_VALIDATE(update_props->GetString(
1112 keys::kUrlKey, &url_string));
1113 GURL url = ResolvePossiblyRelativeURL(url_string, GetExtension());
1114
1115 if (!url.is_valid()) {
1116 error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kInvalidUrlError,
1117 url_string);
1118 return false;
1119 }
1120
1121 // Don't let the extension crash the browser or renderers.
1122 if (IsCrashURL(url)) {
1123 error_ = keys::kNoCrashBrowserError;
1124 return false;
1125 }
1126
1127 // JavaScript URLs can do the same kinds of things as cross-origin XHR, so
1128 // we need to check host permissions before allowing them.
1129 if (url.SchemeIs(chrome::kJavaScriptScheme)) {
1130 if (!GetExtension()->CanExecuteScriptOnPage(
1131 web_contents_->GetURL(), NULL, &error_)) {
1132 return false;
1133 }
1134
1135 ExtensionMsg_ExecuteCode_Params params;
1136 params.request_id = request_id();
1137 params.extension_id = extension_id();
1138 params.is_javascript = true;
1139 params.code = url.path();
1140 params.all_frames = false;
1141 params.in_main_world = true;
1142
1143 RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1144 render_view_host->Send(
1145 new ExtensionMsg_ExecuteCode(render_view_host->routing_id(),
1146 params));
1147
1148 Observe(web_contents_);
1149 AddRef(); // Balanced in OnExecuteCodeFinished().
1150
1151 is_async = true;
1152 }
1153
1154 controller.LoadURL(
1155 url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string());
1156
1157 // The URL of a tab contents never actually changes to a JavaScript URL, so
1158 // this check only makes sense in other cases.
1159 if (!url.SchemeIs(chrome::kJavaScriptScheme))
1160 DCHECK_EQ(url.spec(), web_contents_->GetURL().spec());
1161 }
1162 1109
1163 bool active = false; 1110 bool active = false;
1164 // TODO(rafaelw): Setting |active| from js doesn't make much sense. 1111 // TODO(rafaelw): Setting |active| from js doesn't make much sense.
1165 // Move tab selection management up to window. 1112 // Move tab selection management up to window.
1166 if (update_props->HasKey(keys::kSelectedKey)) 1113 if (update_props->HasKey(keys::kSelectedKey))
1167 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( 1114 EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean(
1168 keys::kSelectedKey, &active)); 1115 keys::kSelectedKey, &active));
1169 1116
1170 // The 'active' property has replaced 'selected'. 1117 // The 'active' property has replaced 'selected'.
1171 if (update_props->HasKey(keys::kActiveKey)) 1118 if (update_props->HasKey(keys::kActiveKey))
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1213 tab_index, &opener_contents->web_contents()->GetController()); 1160 tab_index, &opener_contents->web_contents()->GetController());
1214 } 1161 }
1215 1162
1216 if (!is_async) { 1163 if (!is_async) {
1217 PopulateResult(); 1164 PopulateResult();
1218 SendResponse(true); 1165 SendResponse(true);
1219 } 1166 }
1220 return true; 1167 return true;
1221 } 1168 }
1222 1169
1170 bool UpdateTabFunction::UpdateURLIfPresent(DictionaryValue* update_props,
1171 bool* is_async) {
1172 if (!update_props->HasKey(keys::kUrlKey))
1173 return true;
1174
1175 std::string url_string;
1176 EXTENSION_FUNCTION_VALIDATE(update_props->GetString(
1177 keys::kUrlKey, &url_string));
1178 GURL url = ResolvePossiblyRelativeURL(url_string, GetExtension());
1179
1180 if (!url.is_valid()) {
1181 error_ = ExtensionErrorUtils::FormatErrorMessage(
1182 keys::kInvalidUrlError, url_string);
1183 return false;
1184 }
1185
1186 // Don't let the extension crash the browser or renderers.
1187 if (IsCrashURL(url)) {
1188 error_ = keys::kNoCrashBrowserError;
1189 return false;
1190 }
1191
1192 // JavaScript URLs can do the same kinds of things as cross-origin XHR, so
1193 // we need to check host permissions before allowing them.
1194 if (url.SchemeIs(chrome::kJavaScriptScheme)) {
1195 if (!GetExtension()->CanExecuteScriptOnPage(
1196 web_contents_->GetURL(), NULL, &error_)) {
1197 return false;
1198 }
1199
1200 ExtensionMsg_ExecuteCode_Params params;
1201 params.request_id = request_id();
1202 params.extension_id = extension_id();
1203 params.is_javascript = true;
1204 params.code = url.path();
1205 params.all_frames = false;
1206 params.in_main_world = true;
1207
1208 RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
1209 render_view_host->Send(
1210 new ExtensionMsg_ExecuteCode(render_view_host->routing_id(), params));
1211
1212 Observe(web_contents_);
1213 AddRef(); // Balanced in OnExecuteCodeFinished().
1214
1215 *is_async = true;
1216 return true;
1217 }
1218
1219 web_contents_->GetController().LoadURL(
1220 url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string());
1221
1222 // The URL of a tab contents never actually changes to a JavaScript URL, so
1223 // this check only makes sense in other cases.
1224 if (!url.SchemeIs(chrome::kJavaScriptScheme))
1225 DCHECK_EQ(url.spec(), web_contents_->GetURL().spec());
1226
1227 return true;
1228 }
1229
1223 void UpdateTabFunction::PopulateResult() { 1230 void UpdateTabFunction::PopulateResult() {
1224 if (!has_callback()) 1231 if (!has_callback())
1225 return; 1232 return;
1226 1233
1227 if (GetExtension()->HasAPIPermission(ExtensionAPIPermission::kTab) && 1234 if (GetExtension()->HasAPIPermission(ExtensionAPIPermission::kTab) &&
1228 web_contents_ != NULL) { 1235 web_contents_ != NULL) {
1229 result_.reset(ExtensionTabUtil::CreateTabValue(web_contents_)); 1236 result_.reset(ExtensionTabUtil::CreateTabValue(web_contents_));
1230 } else { 1237 } else {
1231 result_.reset(Value::CreateNullValue()); 1238 result_.reset(Value::CreateNullValue());
1232 } 1239 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1264 if (!error.empty()) { 1271 if (!error.empty()) {
1265 CHECK(!success); 1272 CHECK(!success);
1266 error_ = error; 1273 error_ = error;
1267 } 1274 }
1268 1275
1269 if (success) 1276 if (success)
1270 PopulateResult(); 1277 PopulateResult();
1271 SendResponse(success); 1278 SendResponse(success);
1272 1279
1273 Observe(NULL); 1280 Observe(NULL);
1274 Release(); // Balanced in RunImpl(). 1281 Release(); // Balanced in UpdateURLIfPresent().
1275 } 1282 }
1276 1283
1277 bool MoveTabsFunction::RunImpl() { 1284 bool MoveTabsFunction::RunImpl() {
1278 Value* tab_value = NULL; 1285 Value* tab_value = NULL;
1279 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); 1286 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value));
1280 1287
1281 std::vector<int> tab_ids; 1288 std::vector<int> tab_ids;
1282 EXTENSION_FUNCTION_VALIDATE(ReadOneOrMoreIntegers(tab_value, &tab_ids)); 1289 EXTENSION_FUNCTION_VALIDATE(ReadOneOrMoreIntegers(tab_value, &tab_ids));
1283 1290
1284 DictionaryValue* update_props = NULL; 1291 DictionaryValue* update_props = NULL;
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
1467 // is being dragged, or we're in some other nested event loop. This code 1474 // is being dragged, or we're in some other nested event loop. This code
1468 // path should ensure that the tab is safely closed under such 1475 // path should ensure that the tab is safely closed under such
1469 // circumstances, whereas |Browser::CloseTabContents()| does not. 1476 // circumstances, whereas |Browser::CloseTabContents()| does not.
1470 RenderViewHost* render_view_host = 1477 RenderViewHost* render_view_host =
1471 contents->web_contents()->GetRenderViewHost(); 1478 contents->web_contents()->GetRenderViewHost();
1472 render_view_host->delegate()->Close(render_view_host); 1479 render_view_host->delegate()->Close(render_view_host);
1473 } 1480 }
1474 return true; 1481 return true;
1475 } 1482 }
1476 1483
1477 bool CaptureVisibleTabFunction::RunImpl() { 1484 bool CaptureVisibleTabFunction::GetTabToCapture(
1485 WebContents** web_contents, TabContentsWrapper** wrapper) {
1478 Browser* browser = NULL; 1486 Browser* browser = NULL;
1479 // windowId defaults to "current" window. 1487 // windowId defaults to "current" window.
1480 int window_id = extension_misc::kCurrentWindowId; 1488 int window_id = extension_misc::kCurrentWindowId;
1481 1489
1482 if (HasOptionalArgument(0)) 1490 if (HasOptionalArgument(0))
1483 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); 1491 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id));
1484 1492
1485 if (!GetBrowserFromWindowID(this, window_id, &browser)) 1493 if (!GetBrowserFromWindowID(this, window_id, &browser))
1486 return false; 1494 return false;
1487 1495
1496 *web_contents = browser->GetSelectedWebContents();
1497 if (*web_contents == NULL) {
1498 error_ = keys::kInternalVisibleTabCaptureError;
1499 return false;
1500 }
1501
1502 *wrapper = browser->GetSelectedTabContentsWrapper();
1503
1504 return true;
1505 };
1506
1507 bool CaptureVisibleTabFunction::RunImpl() {
1508 WebContents* web_contents = NULL;
1509 TabContentsWrapper* wrapper = NULL;
1510 if (!GetTabToCapture(&web_contents, &wrapper))
1511 return false;
1512
1488 image_format_ = FORMAT_JPEG; // Default format is JPEG. 1513 image_format_ = FORMAT_JPEG; // Default format is JPEG.
1489 image_quality_ = kDefaultQuality; // Default quality setting. 1514 image_quality_ = kDefaultQuality; // Default quality setting.
1490 1515
1491 if (HasOptionalArgument(1)) { 1516 if (HasOptionalArgument(1)) {
1492 DictionaryValue* options = NULL; 1517 DictionaryValue* options = NULL;
1493 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &options)); 1518 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &options));
1494 1519
1495 if (options->HasKey(keys::kFormatKey)) { 1520 if (options->HasKey(keys::kFormatKey)) {
1496 std::string format; 1521 std::string format;
1497 EXTENSION_FUNCTION_VALIDATE( 1522 EXTENSION_FUNCTION_VALIDATE(
1498 options->GetString(keys::kFormatKey, &format)); 1523 options->GetString(keys::kFormatKey, &format));
1499 1524
1500 if (format == keys::kFormatValueJpeg) { 1525 if (format == keys::kFormatValueJpeg) {
1501 image_format_ = FORMAT_JPEG; 1526 image_format_ = FORMAT_JPEG;
1502 } else if (format == keys::kFormatValuePng) { 1527 } else if (format == keys::kFormatValuePng) {
1503 image_format_ = FORMAT_PNG; 1528 image_format_ = FORMAT_PNG;
1504 } else { 1529 } else {
1505 // Schema validation should make this unreachable. 1530 // Schema validation should make this unreachable.
1506 EXTENSION_FUNCTION_VALIDATE(0); 1531 EXTENSION_FUNCTION_VALIDATE(0);
1507 } 1532 }
1508 } 1533 }
1509 1534
1510 if (options->HasKey(keys::kQualityKey)) { 1535 if (options->HasKey(keys::kQualityKey)) {
1511 EXTENSION_FUNCTION_VALIDATE( 1536 EXTENSION_FUNCTION_VALIDATE(
1512 options->GetInteger(keys::kQualityKey, &image_quality_)); 1537 options->GetInteger(keys::kQualityKey, &image_quality_));
1513 } 1538 }
1514 } 1539 }
1515 1540
1516 WebContents* web_contents = browser->GetSelectedWebContents();
1517 if (!web_contents) {
1518 error_ = keys::kInternalVisibleTabCaptureError;
1519 return false;
1520 }
1521
1522 // captureVisibleTab() can return an image containing sensitive information 1541 // captureVisibleTab() can return an image containing sensitive information
1523 // that the browser would otherwise protect. Ensure the extension has 1542 // that the browser would otherwise protect. Ensure the extension has
1524 // permission to do this. 1543 // permission to do this.
1525 if (!GetExtension()->CanCaptureVisiblePage(web_contents->GetURL(), &error_)) 1544 if (!GetExtension()->CanCaptureVisiblePage(web_contents->GetURL(), &error_))
1526 return false; 1545 return false;
1527 1546
1528 RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
1529
1530 // If a backing store is cached for the tab we want to capture, 1547 // If a backing store is cached for the tab we want to capture,
1531 // and it can be copied into a bitmap, then use it to generate the image. 1548 // and it can be copied into a bitmap, then use it to generate the image.
1532 BackingStore* backing_store = render_view_host->GetBackingStore(false); 1549 if (CaptureSnapshotFromBackingStore(web_contents))
1533 if (backing_store && CaptureSnapshotFromBackingStore(backing_store))
1534 return true; 1550 return true;
1535 1551
1536 // Ask the renderer for a snapshot of the tab. 1552 // Ask the renderer for a snapshot of the tab.
1537 TabContentsWrapper* wrapper = browser->GetSelectedTabContentsWrapper();
1538 wrapper->snapshot_tab_helper()->CaptureSnapshot(); 1553 wrapper->snapshot_tab_helper()->CaptureSnapshot();
1539 registrar_.Add(this, 1554 registrar_.Add(this,
1540 chrome::NOTIFICATION_TAB_SNAPSHOT_TAKEN, 1555 chrome::NOTIFICATION_TAB_SNAPSHOT_TAKEN,
1541 content::Source<TabContentsWrapper>(wrapper)); 1556 content::Source<TabContentsWrapper>(wrapper));
1542 AddRef(); // Balanced in CaptureVisibleTabFunction::Observe(). 1557 AddRef(); // Balanced in CaptureVisibleTabFunction::Observe().
1543 1558
1544 return true; 1559 return true;
1545 } 1560 }
1546 1561
1547 // Build the image of a tab's contents out of a backing store. 1562 // Build the image of a tab's contents out of a backing store.
1548 // This may fail if we can not copy a backing store into a bitmap. 1563 // This may fail if we can not copy a backing store into a bitmap.
1549 // For example, some uncommon X11 visual modes are not supported by 1564 // For example, some uncommon X11 visual modes are not supported by
1550 // CopyFromBackingStore(). 1565 // CopyFromBackingStore().
1551 bool CaptureVisibleTabFunction::CaptureSnapshotFromBackingStore( 1566 bool CaptureVisibleTabFunction::CaptureSnapshotFromBackingStore(
1552 BackingStore* backing_store) { 1567 WebContents* web_contents) {
1568 BackingStore* backing_store =
1569 web_contents->GetRenderViewHost()->GetBackingStore(false);
1570 if (!backing_store)
1571 return false;
1553 1572
1554 skia::PlatformCanvas temp_canvas; 1573 skia::PlatformCanvas temp_canvas;
1555 if (!backing_store->CopyFromBackingStore(gfx::Rect(backing_store->size()), 1574 if (!backing_store->CopyFromBackingStore(gfx::Rect(backing_store->size()),
1556 &temp_canvas)) { 1575 &temp_canvas)) {
1557 return false; 1576 return false;
1558 } 1577 }
1559 VLOG(1) << "captureVisibleTab() got image from backing store."; 1578 VLOG(1) << "captureVisibleTab() got image from backing store.";
1560 1579
1561 SendResultFromBitmap( 1580 SendResultFromBitmap(
1562 skia::GetTopDevice(temp_canvas)->accessBitmap(false)); 1581 skia::GetTopDevice(temp_canvas)->accessBitmap(false));
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1705 // called for every API call the extension made. 1724 // called for every API call the extension made.
1706 GotLanguage(language); 1725 GotLanguage(language);
1707 } 1726 }
1708 1727
1709 void DetectTabLanguageFunction::GotLanguage(const std::string& language) { 1728 void DetectTabLanguageFunction::GotLanguage(const std::string& language) {
1710 result_.reset(Value::CreateStringValue(language.c_str())); 1729 result_.reset(Value::CreateStringValue(language.c_str()));
1711 SendResponse(true); 1730 SendResponse(true);
1712 1731
1713 Release(); // Balanced in Run() 1732 Release(); // Balanced in Run()
1714 } 1733 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698