Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2014 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 /** | 5 /** |
| 6 * Global variable containing the query we'd like to pass to Flickr. In this | 6 * Get the current URL. |
| 7 * case, kittens! | |
| 8 * | 7 * |
| 9 * @type {string} | 8 * @param {function(string)} callback - called when the URL of the current tab |
| 9 * is found. | |
| 10 **/ | |
| 11 function getCurrentTabUrl(callback) { | |
| 12 // Query filter to be passed to chrome.tabs.query - see | |
| 13 // https://developer.chrome.com/extensions/tabs#method-query | |
| 14 var queryInfo = { | |
| 15 active: true, | |
| 16 currentWindow: true | |
| 17 }; | |
| 18 | |
| 19 chrome.tabs.query(queryInfo, function(tabs) { | |
| 20 // chrome.tabs.query invokes the callback with a list of tabs that match the | |
| 21 // query. When the popup is opened, there is certainly a window and at least | |
| 22 // one tab, so we can safely assume that |tabs| is a non-empty array. | |
| 23 // A window can only have one active tab at a time, so the array consists of | |
| 24 // exactly one tab. | |
| 25 var tab = tabs[0]; | |
| 26 | |
| 27 // A tab is a plain object that provides information about the tab. | |
| 28 // See https://developer.chrome.com/extensions/tabs#type-Tab | |
| 29 var url = tab.url; | |
| 30 | |
| 31 // tab.url is only available if the "activeTab" permission is declared. | |
| 32 // If you want to see the URL of other tabs (e.g. after removing active:true | |
| 33 // from |queryInfo|), then the "tabs" permission is required to see their | |
| 34 // "url" properties. | |
| 35 console.assert(typeof url == 'string', 'tab.url should be a string'); | |
| 36 | |
| 37 callback(url); | |
| 38 }); | |
| 39 | |
| 40 // Most methods of the Chrome extension APIs are asynchronous. This means that | |
| 41 // you CANNOT do something like this: | |
| 42 // | |
| 43 // var url; | |
| 44 // chrome.tabs.query(queryInfo, function(tabs) { | |
| 45 // url = tabs[0].url; | |
| 46 // }); | |
| 47 // alert(url); // Shows "undefined", because chrome.tabs.query is async. | |
| 48 } | |
| 49 | |
| 50 /** | |
| 51 * @param {string} searchTerm - Search term for Google Image search. | |
| 52 * @param {function(string,number,number)} callback - Called when an image has | |
| 53 * been found. The callback gets the URL, width and height of the image. | |
| 54 * @param {function(string)} errorCallback - Called when the image is not found. | |
| 55 * The callback gets a string that describes the failure reason. | |
| 10 */ | 56 */ |
| 11 var QUERY = 'kittens'; | 57 function getImageUrl(searchTerm, callback, errorCallback) { |
| 58 // Google image search - 100 searches per day. | |
| 59 // https://developers.google.com/image-search/ | |
| 60 var searchUrl = 'https://ajax.googleapis.com/ajax/services/search/images' + | |
| 61 '?v=1.0&q=' + encodeURIComponent(searchTerm); | |
| 62 var x = new XMLHttpRequest(); | |
| 63 x.open('GET', searchUrl); | |
| 64 // The Google image search API responds with JSON, so let Chrome parse it. | |
| 65 x.responseType = 'json'; | |
| 66 x.onload = function() { | |
| 67 // Parse and process the response from Google Image Search. | |
| 68 var response = x.response; | |
| 69 if (!response || !response.responseData || !response.responseData.results || | |
| 70 response.responseData.results.length === 0) { | |
| 71 errorCallback('No response from Google Image search!'); | |
| 72 return; | |
| 73 } | |
| 74 var firstResult = response.responseData.results[0]; | |
| 75 // Take the thumbnail instead of the full image to get an approximately | |
| 76 // consistent image size. | |
| 77 var imageUrl = firstResult.tbUrl; | |
| 78 var width = parseInt(firstResult.tbWidth); | |
| 79 var height = parseInt(firstResult.tbHeight); | |
| 80 callback(imageUrl, width, height); | |
|
not at google - send to devlin
2014/11/18 16:09:37
You might want to verify imageUrl, and catch width
robwu
2014/11/18 16:13:15
In principle I agree with verifying external data,
not at google - send to devlin
2014/11/18 16:15:20
Frozen APIs are well and good, but bugs and issues
robwu
2014/11/26 17:51:04
Done.
| |
| 81 }; | |
| 82 x.onerror = function() { | |
| 83 errorCallback('Network error.'); | |
| 84 }; | |
| 85 x.send(); | |
| 86 } | |
| 12 | 87 |
| 13 var kittenGenerator = { | 88 function renderStatus(statusText) { |
| 14 /** | 89 document.getElementById('status').textContent = statusText; |
| 15 * Flickr URL that will give us lots and lots of whatever we're looking for. | 90 } |
| 16 * | |
| 17 * See http://www.flickr.com/services/api/flickr.photos.search.html for | |
| 18 * details about the construction of this URL. | |
| 19 * | |
| 20 * @type {string} | |
| 21 * @private | |
| 22 */ | |
| 23 searchOnFlickr_: 'https://secure.flickr.com/services/rest/?' + | |
| 24 'method=flickr.photos.search&' + | |
| 25 'api_key=90485e931f687a9b9c2a66bf58a3861a&' + | |
| 26 'text=' + encodeURIComponent(QUERY) + '&' + | |
| 27 'safe_search=1&' + | |
| 28 'content_type=1&' + | |
| 29 'sort=interestingness-desc&' + | |
| 30 'per_page=20', | |
| 31 | 91 |
| 32 /** | 92 document.addEventListener('DOMContentLoaded', function() { |
| 33 * Sends an XHR GET request to grab photos of lots and lots of kittens. The | 93 getCurrentTabUrl(function(url) { |
| 34 * XHR's 'onload' event is hooks up to the 'showPhotos_' method. | 94 // Put the image URL in Google search. |
| 35 * | 95 renderStatus('Performing Google Image search for ' + url); |
| 36 * @public | |
| 37 */ | |
| 38 requestKittens: function() { | |
| 39 var req = new XMLHttpRequest(); | |
| 40 req.open("GET", this.searchOnFlickr_, true); | |
| 41 req.onload = this.showPhotos_.bind(this); | |
| 42 req.send(null); | |
| 43 }, | |
| 44 | 96 |
| 45 /** | 97 getImageUrl(url, function(imageUrl, width, height) { |
| 46 * Handle the 'onload' event of our kitten XHR request, generated in | |
| 47 * 'requestKittens', by generating 'img' elements, and stuffing them into | |
| 48 * the document for display. | |
| 49 * | |
| 50 * @param {ProgressEvent} e The XHR ProgressEvent. | |
| 51 * @private | |
| 52 */ | |
| 53 showPhotos_: function (e) { | |
| 54 var kittens = e.target.responseXML.querySelectorAll('photo'); | |
| 55 for (var i = 0; i < kittens.length; i++) { | |
| 56 var img = document.createElement('img'); | |
| 57 img.src = this.constructKittenURL_(kittens[i]); | |
| 58 img.setAttribute('alt', kittens[i].getAttribute('title')); | |
| 59 document.body.appendChild(img); | |
| 60 } | |
| 61 }, | |
| 62 | 98 |
| 63 /** | 99 renderStatus('Search term: ' + url + '\n' + |
| 64 * Given a photo, construct a URL using the method outlined at | 100 'Google image search result: ' + imageUrl); |
| 65 * http://www.flickr.com/services/api/misc.urlKittenl | 101 var imageResult = document.getElementById('image-result'); |
| 66 * | 102 // Explicitly set the width/height to minimize the number of reflows. For |
| 67 * @param {DOMElement} A kitten. | 103 // a single image, this does not matter, but if you're going to embed |
| 68 * @return {string} The kitten's URL. | 104 // multiple external images in your page, then the absence of width/height |
| 69 * @private | 105 // attributes causes the popup to resize multiple times. |
| 70 */ | 106 imageResult.width = width; |
| 71 constructKittenURL_: function (photo) { | 107 imageResult.height = height; |
| 72 return "http://farm" + photo.getAttribute("farm") + | 108 imageResult.src = imageUrl; |
| 73 ".static.flickr.com/" + photo.getAttribute("server") + | 109 imageResult.hidden = false; |
| 74 "/" + photo.getAttribute("id") + | |
| 75 "_" + photo.getAttribute("secret") + | |
| 76 "_s.jpg"; | |
| 77 } | |
| 78 }; | |
| 79 | 110 |
| 80 // Run our kitten generation script as soon as the document's DOM is ready. | 111 }, function(errorMessage) { |
| 81 document.addEventListener('DOMContentLoaded', function () { | 112 renderStatus('Cannot display image. ' + errorMessage); |
| 82 kittenGenerator.requestKittens(); | 113 }); |
| 114 }); | |
| 83 }); | 115 }); |
| OLD | NEW |