Guest User

Personal Blocklist Fix

a guest
Aug 3rd, 2015
2,976
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Copyright 2011 Google Inc. All Rights Reserved.
  2.  
  3. /**
  4.  * @fileoverview Applies blocklist features to Google search result pages.
  5.  * @author manuelh@google.com (Manuel Holtz)
  6.  */
  7.  
  8. /**
  9.  * Namespace for the content script functions for Google search result pages.
  10.  * @const
  11.  */
  12. blocklist.serp = {};
  13.  
  14. /**
  15.  * Class of the search results on Google SERP.
  16.  * @type {string}
  17.  */
  18. blocklist.serp.SEARCH_RESULT_CLASS = 'g';
  19.  
  20. /**
  21.  * Class to add to a search result after it was processed by the extension.
  22.  * @type {string}
  23.  */
  24. blocklist.serp.PERSONAL_BLOCKLIST_CLASS = 'pb';
  25.  
  26. /**
  27.  * Class of blocked search results.
  28.  * @type {string}
  29.  */
  30. blocklist.serp.BLOCKED_SEARCH_RESULT_CLASS = 'blocked';
  31.  
  32. /**
  33.  * Class of blocked search results that were requested to be shown.
  34.  * @type {string}
  35.  */
  36. blocklist.serp.BLOCKED_VISIBLE_SEARCH_RESULT_CLASS = 'blockedVisible';
  37.  
  38. /**
  39.  * Class of a element that holds block/unblock links.
  40.  * @type {string}
  41.  */
  42. blocklist.serp.BLOCK_LINK_CLASS = 'fl';
  43.  
  44. /**
  45.  * Class of the search result bodies on Google SERP.
  46.  * @type {string}
  47.  */
  48. blocklist.serp.SEARCH_RESULT_BODY_CLASS = 's';
  49.  
  50. /**
  51.  * Class of the search results lower links on Google SERP.
  52.  * @type {string}
  53.  */
  54. blocklist.serp.SEARCH_RESULT_LOWER_LINKS_CLASS = 'gl';
  55.  
  56. /**
  57.  * Class that contains the cite tag on Google SERP.
  58.  * @type {string}
  59.  */
  60. blocklist.serp.SEARCH_RESULT_CITE_DIV_CLASS = 'kv';
  61.  
  62. /**
  63.  * Class of the short (snippet-less) search results links on Google SERP.
  64.  * @type {string}
  65.  */
  66. blocklist.serp.SEARCH_RESULT_SHORT_LINKS_CLASS = 'vshid';
  67.  
  68. /**
  69.  * Class of lower links span for definition-like results (e.g. query "viagra").
  70.  * @type {string}
  71.  */
  72. blocklist.serp.DEFINITION_RESULT_LOWER_LINKS_CLASS = 'a';
  73.  
  74. /**
  75.  * Class of book search result table cell, used to identify book search results.
  76.  * @type {string}
  77.  */
  78. blocklist.serp.BOOK_SEARCH_RESULT_CLASS = 'bkst';
  79.  
  80. /**
  81.  * Class of the search results block div.
  82.  * @type {string}
  83.  */
  84. blocklist.serp.SEARCH_RESULT_BLOCK_CLASS = 'ires';
  85.  
  86. /**
  87.  * Id of the div that displays the result removal notification.
  88.  * @type {string}
  89.  */
  90. blocklist.serp.NOTIFICATION_DIV_ID = 'blocklistNotification';
  91.  
  92. /**
  93.  * Class name that identifies gws-side block links.
  94.  * @type {string}
  95.  */
  96. blocklist.serp.GWS_BLOCK_LINK_CLASS = 'kob';
  97.  
  98. /**
  99.  * Class name that identifies showed gws-side block links.
  100.  * @type {string}
  101.  */
  102. blocklist.serp.SHOWED_GWS_BLOCK_LINK_CLASS = 'kobb';
  103.  
  104. /**
  105.  * The interval between attempts to apply blocklist feats to SERP, in millisecs.
  106.  * @type {number}
  107.  */
  108. blocklist.serp.REPEAT_INTERVAL_IN_MS = 500;
  109.  
  110. // TODO(manuelh): Use CSS file for styles instead.
  111. /**
  112.  * Style of the notification for removed search results.
  113.  * @type {string}
  114.  */
  115. blocklist.serp.NOTIFICATION_STYLE =
  116.     'font-style:italic;margin-top:1em;margin-bottom:1em;';
  117.  
  118. /**
  119.  * Style for block links. Prevents the word "Block" from appearing on a separate
  120.  * line to the domain being blocked.
  121.  */
  122. blocklist.serp.BLOCK_LINK_STYLE = 'white-space:nowrap;';
  123.  
  124. /**
  125.  * Type of refresh request.
  126.  * @type {string}
  127.  */
  128. blocklist.serp.REFRESH_REQUEST = 'refresh';
  129.  
  130. /**
  131.  * Style of blocked search results that are shown on request.
  132.  * @type {string}
  133.  */
  134. blocklist.serp.BLOCKED_VISIBLE_STYLE = 'display:block;background-color:#FFD2D2';
  135.  
  136. /**
  137.  * A regular expression to deal with redirections through Google services,
  138.  * e.g. for translated results like
  139.  * http://translate.google.com/translate?u=http://example.com
  140.  * @type {RegExp}
  141.  */
  142. blocklist.serp.REDIRECT_REGEX = new RegExp(
  143.     '^(https?://[a-z.]+[.]?google([.][a-z]{2,4}){1,2})?/' +
  144.     '[a-z_-]*[?]((img)?u|.*&(img)?u)(rl)?=([^&]*[.][^&]*).*$');
  145.  
  146. /**
  147.  * A regular expression to check if personalized web search is disabled in url.
  148.  * @type {RegExp}
  149.  */
  150. blocklist.serp.PWS_REGEX = new RegExp('(&|[?])pws=0');
  151.  
  152. /**
  153.  * Matches the kEI javascript property defined in the header of the Google SRP.
  154.  * @type {RegExp}
  155.  */
  156. blocklist.serp.EVENT_ID_REGEX = new RegExp('kEI\\:"([^"]+)"');
  157.  
  158. /**
  159.  * The blocklisted patterns. Call blocklist.serp.refreshBlocklist to populate.
  160.  * @type {Array.<string>}
  161.  */
  162. blocklist.serp.blocklist = [];
  163.  
  164. /**
  165.  * The event id of the search result page.
  166.  * @type {string}
  167.  */
  168. blocklist.serp.eventId = '';
  169.  
  170. /**
  171.  * Whether the current search result page is https page.
  172.  * The extension will not send info back to google via gen204 request if user is
  173.  * under https page.
  174.  * @type {bool}
  175.  */
  176. blocklist.serp.isHttps = false;
  177.  
  178. /**
  179.  * Whether the search result alterations (block links etc) need to be reapplied.
  180.  * Used by blocklist.serp.modifySearchResults_ that constitutes what happens in
  181.  * the main process loop of the extension. This variable primarily helps with
  182.  * efficiency, because it avoids unnecessary repetitions.
  183.  *
  184.  * @type {bool}
  185.  */
  186. blocklist.serp.needsRefresh = false;
  187.  
  188. /**
  189.  * Creates a DOM element containing a "block domain" or "unblock domain" link.
  190.  * @param {function} handler The function to bind to a click.
  191.  * @param {string} pattern The domain pattern to send to the handler on click.
  192.  * @param {string} className Name of the message string and span class.
  193.  * @return {Element} A div element with the block link.
  194.  * @private
  195.  */
  196. blocklist.serp.createLink_ = function(handler, pattern, className) {
  197.   var blockLink = document.createElement('a');
  198.   blockLink.setAttribute('dir', chrome.i18n.getMessage('textDirection'));
  199.   blockLink.className = blocklist.serp.BLOCK_LINK_CLASS;
  200.   blockLink.setAttribute('style', blocklist.serp.BLOCK_LINK_STYLE);
  201.   blockLink.href = 'javascript:;';  // Do nothing, no refresh.
  202.   blockLink.addEventListener(
  203.       'click', function() { handler(pattern) }, false);
  204.  
  205.   // Separate spans to avoid mixing latin chars with Arabic/Hebrew.
  206.   var prefixSpan = document.createElement('span');
  207.   prefixSpan.appendChild(document.createTextNode(
  208.        chrome.i18n.getMessage(className + 'Prefix')));
  209.   var patternSpan = document.createElement('span');
  210.   patternSpan.appendChild(document.createTextNode(pattern));
  211.   var suffixSpan = document.createElement('span');
  212.   suffixSpan.appendChild(document.createTextNode(
  213.       chrome.i18n.getMessage(className + 'Suffix')));
  214.  
  215.   blockLink.appendChild(prefixSpan);
  216.   blockLink.appendChild(patternSpan);
  217.   blockLink.appendChild(suffixSpan);
  218.  
  219.   var blockLinkDiv = document.createElement('div');
  220.   blockLinkDiv.className = className;
  221.   blockLinkDiv.appendChild(blockLink);
  222.   return blockLinkDiv;
  223. };
  224.  
  225. /**
  226.  * Adds a block or unblock link to a search result.
  227.  * @param {Element} searchResult Search result list element, including children.
  228.  * @param {Object} linkDiv Div element with the link to add.
  229.  */
  230. blocklist.serp.addLink = function(searchResult, linkDiv) {
  231.   var regularResultSpan = searchResult.querySelector(
  232.       'div.' + blocklist.serp.SEARCH_RESULT_CITE_DIV_CLASS);
  233.   var definitionResultSpan = searchResult.querySelector(
  234.       'span.' + blocklist.serp.DEFINITION_RESULT_LOWER_LINKS_CLASS);
  235.   var shortResultDiv = searchResult.querySelector(
  236.       'div.' + blocklist.serp.SEARCH_RESULT_BODY_CLASS +
  237.       ' span.' + blocklist.serp.SEARCH_RESULT_SHORT_LINKS_CLASS);
  238.   if (regularResultSpan !== null) {
  239.     regularResultSpan.parentNode.appendChild(linkDiv);
  240.   } else if (definitionResultSpan !== null) {
  241.     definitionResultSpan.parentNode.parentNode.appendChild(linkDiv);
  242.   } else if (shortResultDiv !== null) {
  243.     shortResultDiv.parentNode.parentNode.appendChild(linkDiv);
  244.   }
  245. };
  246.  
  247. /**
  248.  * Adds a DOM element containing a notification for removed results.
  249.  * @private
  250.  */
  251. blocklist.serp.addBlockListNotification_ = function() {
  252.   var showBlockedLink = document.createElement('a');
  253.   showBlockedLink.href = 'javascript:;';  // Do nothing, no refresh.
  254.   showBlockedLink.appendChild(document.createTextNode(
  255.       chrome.i18n.getMessage('showBlockedLink')));
  256.   showBlockedLink.addEventListener(
  257.       'click', function() { blocklist.serp.showBlockedResults_() }, false);
  258.  
  259.   var blocklistNotification = document.createElement('div');
  260.   blocklistNotification.id = blocklist.serp.NOTIFICATION_DIV_ID;
  261.   blocklistNotification.setAttribute(
  262.       'dir', chrome.i18n.getMessage('textDirection'));
  263.   blocklistNotification.appendChild(document.createTextNode(
  264.       chrome.i18n.getMessage('blocklistNotification') + ' ('));
  265.   blocklistNotification.appendChild(showBlockedLink);
  266.   blocklistNotification.appendChild(document.createTextNode(').'));
  267.   blocklistNotification.setAttribute(
  268.       'style', blocklist.serp.NOTIFICATION_STYLE);
  269.  
  270.   searchResultBlock = document.querySelector(
  271.       'div#' + blocklist.serp.SEARCH_RESULT_BLOCK_CLASS);
  272.   searchResultBlock.parentNode.insertBefore(blocklistNotification,
  273.                                             searchResultBlock.nextSibling);
  274. };
  275.  
  276. /**
  277.  * Makes blocked search results visible again.
  278.  * @private
  279.  */
  280. blocklist.serp.showBlockedResults_ = function() {
  281.   var blockedResultList = document.querySelectorAll(
  282.       'div.' + blocklist.serp.BLOCKED_SEARCH_RESULT_CLASS);
  283.   for (var i = 0; i < blockedResultList.length; i++) {
  284.     blockedResultList[i].setAttribute('style',
  285.                                      blocklist.serp.BLOCKED_VISIBLE_STYLE);
  286.     blockedResultList[i].className = blocklist.common.removeClass(
  287.         blockedResultList[i].className,
  288.         blocklist.serp.BLOCKED_SEARCH_RESULT_CLASS);
  289.     blockedResultList[i].className = blocklist.common.addClass(
  290.         blockedResultList[i].className,
  291.         blocklist.serp.BLOCKED_VISIBLE_SEARCH_RESULT_CLASS);
  292.   }
  293.   blocklist.serp.needsRefresh = true;
  294. };
  295.  
  296. /**
  297.  * Adds a pattern to the blocklist.
  298.  * @param {string} pattern The pattern to blocklist.
  299.  * @private
  300.  */
  301. blocklist.serp.addBlocklistPattern_ = function(pattern) {
  302.   chrome.extension.sendRequest({type: blocklist.common.ADDTOBLOCKLIST,
  303.                                 pattern: pattern,
  304.                                 ei: blocklist.serp.eventId,
  305.                                 enc: blocklist.serp.isHttps},
  306.                                blocklist.serp.handleAddToBlocklistResponse);
  307. };
  308.  
  309. /**
  310.  * Removes a pattern from the blocklist.
  311.  * @param {string} pattern The pattern to remove from the blocklist.
  312.  * @private
  313.  */
  314. blocklist.serp.removeBlocklistPattern_ = function(pattern) {
  315.   chrome.extension.sendRequest(
  316.       {type: blocklist.common.DELETEFROMBLOCKLIST,
  317.        pattern: pattern,
  318.        ei: blocklist.serp.eventId,
  319.        enc: blocklist.serp.isHttps},
  320.       blocklist.serp.handleDeleteFromBlocklistResponse);
  321. };
  322.  
  323. /**
  324.  * Parses the domain out of a Google search result page.
  325.  * @param {Object} searchResult Search result list element (including children).
  326.  * @return {string} A domain if found; or an empty string.
  327.  * @private
  328.  */
  329. blocklist.serp.parseDomainFromSearchResult_ = function(searchResult) {
  330.   var searchResultAnchor = searchResult.querySelector('h3 > a');
  331.   if (searchResultAnchor === null) {
  332.     return '';
  333.   }
  334.   var url = searchResultAnchor.getAttribute('href');
  335.   // Sometimes, the link is an intermediate step through another google service,
  336.   // for example Google Translate. This regex parses the target url, so that we
  337.   // don't block translate.google.com instead of the target host.
  338.   url = url.replace(blocklist.serp.REDIRECT_REGEX, '$7');
  339.   // Identify domain by stripping protocol and path.
  340.   return url.replace(blocklist.common.HOST_REGEX, '$2');
  341. };
  342.  
  343. /**
  344.  * Determines if and in which way a result result needs to be modified.
  345.  * @param {Element} searchResult Search result list element, including children.
  346.  * @private
  347.  */
  348. blocklist.serp.alterSearchResultNode_ = function(searchResult) {
  349.   var host = blocklist.serp.parseDomainFromSearchResult_(searchResult);
  350.   if (!host) {
  351.     return;
  352.   }
  353.  
  354.   // Skip if there is already a gws-side block link, this is a book search
  355.   // vertical results, or an internal url that was not resolved.
  356.   if (searchResult.querySelector(
  357.           '.' + blocklist.serp.GWS_BLOCK_LINK_CLASS) !== null ||
  358.       searchResult.querySelector(
  359.           'td.' + blocklist.serp.BOOK_SEARCH_RESULT_CLASS) !== null ||
  360.       host[0] == '/') {
  361.     // Mark search result as processed.
  362.     searchResult.className = blocklist.common.addClass(
  363.         searchResult.className, blocklist.serp.PERSONAL_BLOCKLIST_CLASS);
  364.     return;
  365.   }
  366.  
  367.   // Any currently appended block/unblock links need to be replaced.
  368.   blockLink = searchResult.querySelector('div.blockLink');
  369.   unblockLink = searchResult.querySelector('div.unblockLink');
  370.  
  371.   // Two main cases where we need to take action:
  372.   // 1. search result should have a block link and doesn't have one already.
  373.   // 2. search result should have an unblock link and doesn't have one already.
  374.   if (blockLink === null &&
  375.       (blocklist.common.hasClass(
  376.            searchResult.className,
  377.            blocklist.serp.BLOCKED_VISIBLE_SEARCH_RESULT_CLASS) == false)) {
  378.     var blockLinkDiv = blocklist.serp.createLink_(
  379.         blocklist.serp.addBlocklistPattern_, host, 'blockLink');
  380.  
  381.     // Replace existing link, or append.
  382.     if (unblockLink !== null) {
  383.       unblockLink.parentNode.replaceChild(blockLinkDiv, unblockLink);
  384.     } else {
  385.       blocklist.serp.addLink(searchResult, blockLinkDiv);
  386.     }
  387.   } else if (unblockLink === null &&
  388.              blocklist.common.hasClass(
  389.                  searchResult.className,
  390.                  blocklist.serp.BLOCKED_VISIBLE_SEARCH_RESULT_CLASS)) {
  391.     // Use the pattern that caused the block, which might differ from host.
  392.     var blockPattern = blocklist.serp.findBlockPatternForHost_(host);
  393.     if (!blockPattern) {
  394.       return;
  395.     }
  396.     var unblockLinkDiv = blocklist.serp.createLink_(
  397.         blocklist.serp.removeBlocklistPattern_, blockPattern, 'unblockLink');
  398.  
  399.     // Replace existing link, or append.
  400.     if (blockLink !== null) {
  401.       blockLink.parentNode.replaceChild(unblockLinkDiv, blockLink);
  402.     } else {
  403.       blocklist.serp.addLink(searchResult, unblockLinkDiv);
  404.     }
  405.   }
  406.   // Mark search result as processed.
  407.   searchResult.className = blocklist.common.addClass(
  408.       searchResult.className, blocklist.serp.PERSONAL_BLOCKLIST_CLASS);
  409. };
  410.  
  411. /**
  412.  * Removes a search result from the page.
  413.  * @param {Object} searchResult Search result list element (including children).
  414.  */
  415. blocklist.serp.hideSearchResult = function(searchResult) {
  416.   searchResult.setAttribute('style', 'display:none;');
  417.   searchResult.className = blocklist.common.addClass(
  418.       searchResult.className, blocklist.serp.BLOCKED_SEARCH_RESULT_CLASS);
  419. };
  420.  
  421. /**
  422.  * Return a list of subdomains. for example, a.d.c.d will return
  423.  * c.d, d.c.d and a.b.c.d
  424.  * @param {string} pattern The domains pattern to extract subdomains.
  425.  * @return {Array.<string>} Suddomain list.
  426.  * @private
  427.  */
  428. blocklist.serp.extractSubDomains_ = function(pattern) {
  429.   var subdomains = [];
  430.   var parts = pattern.split('.');
  431.   for (var i = parts.length - 2; i >= 0; --i) {
  432.     subdomains.push(parts.slice(i).join('.'));
  433.   }
  434.   return subdomains;
  435. };
  436.  
  437. /**
  438.  * Checks a hostname against the blocklist patterns.
  439.  * @param {string} hostName Host of a search result link.
  440.  * @return {string} A blocklist pattern that matched the host (or empty string).
  441.  * @private
  442.  */
  443. blocklist.serp.findBlockPatternForHost_ = function(hostName) {
  444.   var matchedPattern = '';
  445.   // Match each level of subdomains against the blocklist. For example, if
  446.   // a.com is blocked, b.a.com should be hidden from search result.
  447.   var subdomains = blocklist.serp.extractSubDomains_(hostName);
  448.   for (var j = 0; j < subdomains.length; ++j) {
  449.     if (blocklist.serp.blocklist.indexOf(subdomains[j]) != -1) {
  450.       matchedPattern = subdomains[j];
  451.       break;
  452.     }
  453.   }
  454.   return matchedPattern;
  455. };
  456.  
  457. /**
  458.  * Removes all search results that match the blocklist.
  459.  */
  460. blocklist.serp.hideSearchResults = function() {
  461.   var searchResultList = document.querySelectorAll(
  462.       'div.' + blocklist.serp.SEARCH_RESULT_CLASS);
  463.   for (var i = 0; i < searchResultList.length; i++) {
  464.     var searchResult = searchResultList[i];
  465.     var matchedPattern = blocklist.serp.findBlockPatternForHost_(
  466.         blocklist.serp.parseDomainFromSearchResult_(searchResult));
  467.  
  468.     if (matchedPattern &&
  469.         ((blocklist.common.hasClass(
  470.              searchResult.className,
  471.              blocklist.serp.BLOCKED_SEARCH_RESULT_CLASS) == false) &&
  472.          (blocklist.common.hasClass(
  473.              searchResult.className,
  474.              blocklist.serp.BLOCKED_VISIBLE_SEARCH_RESULT_CLASS) == false))) {
  475.       if (blocklist.common.hasClass(searchResult.parentNode.className,
  476.              blocklist.serp.SHOWED_GWS_BLOCK_LINK_CLASS) == true) {
  477.         searchResult.setAttribute('style',
  478.                                           blocklist.serp.BLOCKED_VISIBLE_STYLE);
  479.         searchResult.className = blocklist.common.removeClass(
  480.             searchResult.className,
  481.             blocklist.serp.BLOCKED_SEARCH_RESULT_CLASS);
  482.         searchResult.className = blocklist.common.addClass(
  483.             searchResult.className,
  484.             blocklist.serp.BLOCKED_VISIBLE_SEARCH_RESULT_CLASS);
  485.       } else {
  486.         blocklist.serp.hideSearchResult(searchResult);
  487.       }
  488.     }
  489.  
  490.     if (!matchedPattern) {
  491.       if (blocklist.common.hasClass(
  492.               searchResult.className,
  493.               blocklist.serp.BLOCKED_SEARCH_RESULT_CLASS) ||
  494.           blocklist.common.hasClass(
  495.               searchResult.className,
  496.               blocklist.serp.BLOCKED_VISIBLE_SEARCH_RESULT_CLASS)) {
  497.         searchResult.className = blocklist.common.removeClass(
  498.             searchResult.className,
  499.             blocklist.serp.BLOCKED_VISIBLE_SEARCH_RESULT_CLASS);
  500.         searchResult.className = blocklist.common.removeClass(
  501.             searchResult.className,
  502.             blocklist.serp.BLOCKED_SEARCH_RESULT_CLASS);
  503.         searchResult.setAttribute('style', 'background-color:inherit;');
  504.       }
  505.     }
  506.   }
  507. };
  508.  
  509. /**
  510.  * Iterates through search results, adding links and applying blocklist filter.
  511.  * @private
  512.  */
  513. blocklist.serp.modifySearchResults_ = function() {
  514.   // Skip if personalized web search was explicitly disabled (&pws=0).
  515.   if (blocklist.serp.IsPwsDisabled_() == true) {
  516.     return;
  517.   }
  518.   // Apply blocklist filter.
  519.   if (blocklist.serp.blocklist.length > 0 || blocklist.serp.needsRefresh) {
  520.     blocklist.serp.hideSearchResults();
  521.   }
  522.   var searchResultList = document.querySelectorAll(
  523.       'div.' + blocklist.serp.SEARCH_RESULT_CLASS);
  524.   var processedSearchResultList = document.querySelectorAll(
  525.       'li.' + blocklist.serp.PERSONAL_BLOCKLIST_CLASS);
  526.  
  527.   // Add blocklist links to search results until all have been processed.
  528.   if (blocklist.serp.needsRefresh ||
  529.       processedSearchResultList.length < searchResultList.length) {
  530.     for (var i = 0; i < searchResultList.length; i++) {
  531.       blocklist.serp.alterSearchResultNode_(searchResultList[i]);
  532.     }
  533.  
  534.     // Add/hide/show notification for removed results.
  535.     var notificationDiv = document.querySelector(
  536.         'div#' + blocklist.serp.NOTIFICATION_DIV_ID);
  537.     var blockedResults = document.querySelectorAll(
  538.         'div.' + blocklist.serp.BLOCKED_SEARCH_RESULT_CLASS);
  539.  
  540.     if (blockedResults.length > 0) {
  541.       if (!notificationDiv) {
  542.         blocklist.serp.addBlockListNotification_();
  543.       } else {
  544.         notificationDiv.setAttribute('style',
  545.                                      blocklist.serp.NOTIFICATION_STYLE);
  546.       }
  547.     } else if (notificationDiv != null) {
  548.       notificationDiv.setAttribute('style', 'display:none;');
  549.     }
  550.  
  551.     blocklist.serp.needsRefresh = false;
  552.   }
  553. };
  554.  
  555. /**
  556.  * Starts an infinite loop that applies the blocklist features to the page.
  557.  * @private
  558.  */
  559. blocklist.serp.applyBlocklistFeatures_ = function() {
  560.   window.setInterval(function() {
  561.     blocklist.serp.modifySearchResults_();
  562.   }, blocklist.serp.REPEAT_INTERVAL_IN_MS);
  563. };
  564.  
  565. /**
  566.  * Callback that handles the response of the local storage request.
  567.  * @param {Array} response Response from the background page listener.
  568.  */
  569. blocklist.serp.handleAddToBlocklistResponse = function(response) {
  570.   if (response.success) {
  571.     blocklist.serp.refreshBlocklist();
  572.     blocklist.serp.needsRefresh = true;
  573.   }
  574. };
  575.  
  576. /**
  577.  * Callback that handles the response of the local storage request.
  578.  * @param {Array} response Response from the background page listener.
  579.  */
  580. blocklist.serp.handleDeleteFromBlocklistResponse = function(response) {
  581.   if (response.success) {
  582.     // Reset blocked results and refresh.
  583.     var searchResultList = document.querySelectorAll(
  584.         'div.' + blocklist.serp.SEARCH_RESULT_CLASS);
  585.     for (var i = 0; i < searchResultList.length; i++) {
  586.       var pattern = blocklist.serp.parseDomainFromSearchResult_(
  587.           searchResultList[i]);
  588.       var subdomains = blocklist.serp.extractSubDomains_(pattern);
  589.       if (blocklist.common.hasClass(
  590.               searchResultList[i].className,
  591.               blocklist.serp.BLOCKED_VISIBLE_SEARCH_RESULT_CLASS) &&
  592.           subdomains.indexOf(response.pattern) != -1) {
  593.         searchResultList[i].className = blocklist.common.removeClass(
  594.             searchResultList[i].className,
  595.             blocklist.serp.BLOCKED_VISIBLE_SEARCH_RESULT_CLASS);
  596.         searchResultList[i].className = blocklist.common.removeClass(
  597.             searchResultList[i].className,
  598.             blocklist.serp.BLOCKED_SEARCH_RESULT_CLASS);
  599.         // Clear the search result's background.
  600.         searchResultList[i].setAttribute('style', 'background-color:inherit;');
  601.       }
  602.     }
  603.     blocklist.serp.refreshBlocklist();
  604.     blocklist.serp.needsRefresh = true;
  605.   }
  606. };
  607.  
  608. /**
  609.  * Callback that handles the response of the local storage request.
  610.  * @param {Array} response Response from the background page listener.
  611.  */
  612. blocklist.serp.handleGetBlocklistResponse = function(response) {
  613.   if (response.blocklist != undefined) {
  614.     blocklist.serp.blocklist = response.blocklist;
  615.   }
  616. };
  617.  
  618. /**
  619.  * Retrieves blocklisted domains from localstorage.
  620.  */
  621. blocklist.serp.refreshBlocklist = function() {
  622.   chrome.extension.sendRequest({type: blocklist.common.GETBLOCKLIST},
  623.                                blocklist.serp.handleGetBlocklistResponse);
  624. };
  625.  
  626. /**
  627.  * Get if the current page is using https protocol.
  628.  * @private
  629.  */
  630. blocklist.serp.getIsHttpsPage_ = function() {
  631.   blocklist.serp.isHttps =
  632.       (document.URL.indexOf('https://') == 0);
  633. };
  634.  
  635. /**
  636.  * Check if personalized web search is disabled (pws parameter is 0).
  637.  * @return {boolean} True if url indicates personalized web search was disabled.
  638.  * @private
  639.  */
  640. blocklist.serp.IsPwsDisabled_ = function() {
  641.   return document.URL.match(blocklist.serp.PWS_REGEX) !== null;
  642. };
  643.  
  644. /**
  645.  * Get event id of this search result page.
  646.  * @private
  647.  */
  648. blocklist.serp.getEventId_ = function() {
  649.   blocklist.serp.eventId = 'null';
  650.   try {
  651.     var head = document.getElementsByTagName('head')[0];
  652.     var scripts = head.getElementsByTagName('script');
  653.     for (var i = 0; i < scripts.length; i++) {
  654.       var script = scripts[i];
  655.       var match = script.text.match(blocklist.serp.EVENT_ID_REGEX);
  656.       if (match) {
  657.         blocklist.serp.eventId = match[1];
  658.       }
  659.     }
  660.   } catch (e) {
  661.   }
  662. };
  663.  
  664. /**
  665.  * Exposes a listener, so that it can accept refresh request from manager.
  666.  */
  667. blocklist.serp.startBackgroundListeners = function() {
  668.   chrome.extension.onRequest
  669.         .addListener(function(request, sender, sendResponse) {
  670.     if (request.type == blocklist.serp.REFRESH_REQUEST) {
  671.       blocklist.serp.refreshBlocklist();
  672.       blocklist.serp.needsRefresh = true;
  673.     } else if (request.type == blocklist.serp.EXPORTTOGOOGLE_REQUEST) {
  674.       document.write(request.html);
  675.       chrome.extension.sendRequest({type: blocklist.common.FINISHEXPORT});
  676.     }
  677.   });
  678. };
  679.  
  680. blocklist.serp.getIsHttpsPage_();
  681. blocklist.serp.getEventId_();
  682. blocklist.serp.refreshBlocklist();
  683. blocklist.serp.applyBlocklistFeatures_();
  684. blocklist.serp.startBackgroundListeners();
RAW Paste Data