Dropped support for Chrome 16, using only webRequest API for blocking
authorWladimir Palant <trev@adblockplus.org>
Fri, 10 Feb 2012 15:15:35 +0100
changeset 76658fccb57e62d
parent 765 0c80acbc4bc0
child 767 13fd0ec5826c
Dropped support for Chrome 16, using only webRequest API for blocking
_locales/ar/messages.json
_locales/de/messages.json
_locales/en/messages.json
_locales/es/messages.json
_locales/fi/messages.json
_locales/fr/messages.json
_locales/he/messages.json
_locales/hu/messages.json
_locales/it/messages.json
_locales/ko/messages.json
_locales/lv/messages.json
_locales/pl/messages.json
_locales/pt_BR/messages.json
_locales/ru/messages.json
_locales/sv/messages.json
_locales/vi/messages.json
_locales/zh_CN/messages.json
_locales/zh_TW/messages.json
background.html
build.py
include.experimental.js
include.postload.js
include.preload.js
include.youtube.js
manifest.json
options.html
update_locales.py
webrequest.js
     1.1 --- a/_locales/ar/messages.json
     1.2 +++ b/_locales/ar/messages.json
     1.3 @@ -13,19 +13,16 @@
     1.4      "message": "إضافة الفلاتر؟"
     1.5    }, 
     1.6    "add_your_own_filters": {
     1.7      "message": "أضف الفلاتر الخاصة بك"
     1.8    }, 
     1.9    "apply_changes": {
    1.10      "message": "تطبيق التغييرات"
    1.11    }, 
    1.12 -  "block_youtube": {
    1.13 -    "message": "منع الإعلانات داخل YouTube videos"
    1.14 -  }, 
    1.15    "cancel": {
    1.16      "description": "Cancel button label", 
    1.17      "message": "إلغاء"
    1.18    }, 
    1.19    "clickhide_instructions": {
    1.20      "message": "بعد إغلاق هذه النافذة. إضغط (او إضغط بالزر اليمين) على أحد العناصر في الصفحة"
    1.21    }, 
    1.22    "description": {
     2.1 --- a/_locales/de/messages.json
     2.2 +++ b/_locales/de/messages.json
     2.3 @@ -17,19 +17,16 @@
     2.4    }, 
     2.5    "apply_changes": {
     2.6      "message": "Änderungen übernehmen"
     2.7    }, 
     2.8    "block_element": {
     2.9      "description": "Name für Kontextmenü-Eintrag 'Element blocken'", 
    2.10      "message": "Element blocken"
    2.11    }, 
    2.12 -  "block_youtube": {
    2.13 -    "message": "Blocke Werbung in YouTube Videos"
    2.14 -  }, 
    2.15    "cancel": {
    2.16      "description": "Name für den 'Abbrechen'-Button", 
    2.17      "message": "Abbrechen"
    2.18    }, 
    2.19    "clickhide_instructions": {
    2.20      "message": "Nachdem dieses Fenster geschlossen ist, klicken Sie ein Element auf der Seite an, welches Sie blockieren wollen."
    2.21    }, 
    2.22    "description": {
     3.1 --- a/_locales/en/messages.json
     3.2 +++ b/_locales/en/messages.json
     3.3 @@ -17,19 +17,16 @@
     3.4    }, 
     3.5    "apply_changes": {
     3.6      "message": "Apply changes"
     3.7    }, 
     3.8    "block_element": {
     3.9      "description": "Label for 'Block Element' context menu item", 
    3.10      "message": "Block Element"
    3.11    }, 
    3.12 -  "block_youtube": {
    3.13 -    "message": "Block ads inside YouTube videos"
    3.14 -  }, 
    3.15    "cancel": {
    3.16      "description": "Cancel button label", 
    3.17      "message": "Cancel"
    3.18    }, 
    3.19    "clickhide_instructions": {
    3.20      "message": "After closing this popup, click (or right-click) an element on the page."
    3.21    }, 
    3.22    "description": {
     4.1 --- a/_locales/es/messages.json
     4.2 +++ b/_locales/es/messages.json
     4.3 @@ -17,19 +17,16 @@
     4.4    }, 
     4.5    "apply_changes": {
     4.6      "message": "Aplicar cambios"
     4.7    }, 
     4.8    "block_element": {
     4.9      "description": "Label for 'Block Element' context menu item", 
    4.10      "message": "Bloquear Elemento"
    4.11    }, 
    4.12 -  "block_youtube": {
    4.13 -    "message": "Desactivar anuncios dentro de los vídeos de YouTube"
    4.14 -  }, 
    4.15    "cancel": {
    4.16      "description": "Cancel button label", 
    4.17      "message": "Cancelar"
    4.18    }, 
    4.19    "clickhide_instructions": {
    4.20      "message": "Después de cerrar este menú desplegable, da clic (o clic derecho) en un elemento de la página."
    4.21    }, 
    4.22    "description": {
     5.1 --- a/_locales/fi/messages.json
     5.2 +++ b/_locales/fi/messages.json
     5.3 @@ -13,19 +13,16 @@
     5.4      "message": "Lisää suodatin?"
     5.5    }, 
     5.6    "add_your_own_filters": {
     5.7      "message": "Lisää omia suodattimia"
     5.8    }, 
     5.9    "apply_changes": {
    5.10      "message": "Hyväksy muutokset"
    5.11    }, 
    5.12 -  "block_youtube": {
    5.13 -    "message": "Estä YouTube videoiden sisaiset mainokset (ei toimi Flash Block laajennuksen kanssa)"
    5.14 -  }, 
    5.15    "cancel": {
    5.16      "description": "Cancel button label", 
    5.17      "message": "Peruuta"
    5.18    }, 
    5.19    "clickhide_instructions": {
    5.20      "message": "Tämän ikkunan sulkemisen jälkeen klikkaa (tai oikea klikkaa) elementtiä jonka haluat estää."
    5.21    }, 
    5.22    "description": {
     6.1 --- a/_locales/fr/messages.json
     6.2 +++ b/_locales/fr/messages.json
     6.3 @@ -16,19 +16,16 @@
     6.4      "message": "Ajouter vos propres filtres"
     6.5    }, 
     6.6    "apply_changes": {
     6.7      "message": "Appliquer"
     6.8    }, 
     6.9    "block_element": {
    6.10      "message": "Supprimer l'élément"
    6.11    }, 
    6.12 -  "block_youtube": {
    6.13 -    "message": "Retirer les publicités dans les vidéos YouTube"
    6.14 -  }, 
    6.15    "cancel": {
    6.16      "description": "Cancel button label", 
    6.17      "message": "Annuler"
    6.18    }, 
    6.19    "clickhide_instructions": {
    6.20      "message": "Après avoir clôturé ce popup, cliquez (ou droit-cliquez) un élément sur la page."
    6.21    }, 
    6.22    "description": {
     7.1 --- a/_locales/he/messages.json
     7.2 +++ b/_locales/he/messages.json
     7.3 @@ -13,19 +13,16 @@
     7.4      "message": "האם להוסיף מסנן/ים?"
     7.5    }, 
     7.6    "add_your_own_filters": {
     7.7      "message": "הוספת מסננים משלך"
     7.8    }, 
     7.9    "apply_changes": {
    7.10      "message": "החלת השינויים"
    7.11    }, 
    7.12 -  "block_youtube": {
    7.13 -    "message": "חסימת פרסומות בתוך סרטוני YouTube"
    7.14 -  }, 
    7.15    "cancel": {
    7.16      "description": "Cancel button label", 
    7.17      "message": "ביטול"
    7.18    }, 
    7.19    "clickhide_instructions": {
    7.20      "message": "לאחר סגירת חלונית זו, יש ללחוץ (לא משנה באיזה לחצן) על רכיב בעמוד זה."
    7.21    }, 
    7.22    "description": {
     8.1 --- a/_locales/hu/messages.json
     8.2 +++ b/_locales/hu/messages.json
     8.3 @@ -13,19 +13,16 @@
     8.4      "message": "Szűrő(k) hozzáadása?"
     8.5    }, 
     8.6    "add_your_own_filters": {
     8.7      "message": "Add hozzá a saját szűrőidet"
     8.8    }, 
     8.9    "apply_changes": {
    8.10      "message": "Változtatások alkalmazása"
    8.11    }, 
    8.12 -  "block_youtube": {
    8.13 -    "message": "Youtube videókon belüli reklámok tiltása"
    8.14 -  }, 
    8.15    "cancel": {
    8.16      "description": "Cancel button label", 
    8.17      "message": "Mégse"
    8.18    }, 
    8.19    "clickhide_instructions": {
    8.20      "message": "Miután bezártad ezt a buborékot, kattints egy elemre az oldalon.."
    8.21    }, 
    8.22    "description": {
     9.1 --- a/_locales/it/messages.json
     9.2 +++ b/_locales/it/messages.json
     9.3 @@ -17,19 +17,16 @@
     9.4    }, 
     9.5    "apply_changes": {
     9.6      "message": "Applica modifiche"
     9.7    }, 
     9.8    "block_element": {
     9.9      "description": "Label for 'Block Element' context menu item", 
    9.10      "message": "Blocca Elemento"
    9.11    }, 
    9.12 -  "block_youtube": {
    9.13 -    "message": "Blocca la pubblicità nei video YouTube"
    9.14 -  }, 
    9.15    "cancel": {
    9.16      "description": "Cancel button label", 
    9.17      "message": "Annulla"
    9.18    }, 
    9.19    "clickhide_instructions": {
    9.20      "message": "Dopo la chiusura di questo pop-up, cliccate (o clic destro) su un elemento sulla pagina."
    9.21    }, 
    9.22    "description": {
    10.1 --- a/_locales/ko/messages.json
    10.2 +++ b/_locales/ko/messages.json
    10.3 @@ -17,19 +17,16 @@
    10.4    }, 
    10.5    "apply_changes": {
    10.6      "message": "적용"
    10.7    }, 
    10.8    "block_element": {
    10.9      "description": "Label for 'Block Element' context menu item", 
   10.10      "message": "요소 숨김"
   10.11    }, 
   10.12 -  "block_youtube": {
   10.13 -    "message": "유튜브 동영상 내부의 광고 차단"
   10.14 -  }, 
   10.15    "cancel": {
   10.16      "description": "Cancel button label", 
   10.17      "message": "취소"
   10.18    }, 
   10.19    "clickhide_instructions": {
   10.20      "message": "이 팝업을 닫은 후 웹 페이지에서 HTML 요소를 클릭하십시오."
   10.21    }, 
   10.22    "description": {
    11.1 --- a/_locales/lv/messages.json
    11.2 +++ b/_locales/lv/messages.json
    11.3 @@ -17,19 +17,16 @@
    11.4    }, 
    11.5    "apply_changes": {
    11.6      "message": "Pielietot izmaiņas"
    11.7    }, 
    11.8    "block_element": {
    11.9      "description": "Label for 'Block Element' context menu item", 
   11.10      "message": "Bloķēt elementu"
   11.11    }, 
   11.12 -  "block_youtube": {
   11.13 -    "message": "Bloķēt reklāmas YouTube videoklipos"
   11.14 -  }, 
   11.15    "cancel": {
   11.16      "description": "Cancel button label", 
   11.17      "message": "Atcelt"
   11.18    }, 
   11.19    "clickhide_instructions": {
   11.20      "message": "Pēc šī aizvēršanas, noklikšķiniet (vai noklikšķiniet ar labo pogu) uz elementa šajā lapā."
   11.21    }, 
   11.22    "description": {
    12.1 --- a/_locales/pl/messages.json
    12.2 +++ b/_locales/pl/messages.json
    12.3 @@ -17,19 +17,16 @@
    12.4    }, 
    12.5    "apply_changes": {
    12.6      "message": "Zakceptuj zmiany"
    12.7    }, 
    12.8    "block_element": {
    12.9      "description": "Label for 'Block Element' context menu item", 
   12.10      "message": "Blokuj Element"
   12.11    }, 
   12.12 -  "block_youtube": {
   12.13 -    "message": "Blokuj reklamy w filmach YouTube"
   12.14 -  }, 
   12.15    "cancel": {
   12.16      "description": "Cancel button label", 
   12.17      "message": "Anuluj"
   12.18    }, 
   12.19    "clickhide_instructions": {
   12.20      "message": "Po zamknięciu tego okna, kliknij lewym (lub prawym) przyciskiem myszy w niechciany element na stronie."
   12.21    }, 
   12.22    "description": {
    13.1 --- a/_locales/pt_BR/messages.json
    13.2 +++ b/_locales/pt_BR/messages.json
    13.3 @@ -17,19 +17,16 @@
    13.4    }, 
    13.5    "apply_changes": {
    13.6      "message": "Aplicar mudanças"
    13.7    }, 
    13.8    "block_element": {
    13.9      "description": "Legenda para o item 'Bloquear Elemento' no menu de contexto", 
   13.10      "message": "Bloquear Elemento"
   13.11    }, 
   13.12 -  "block_youtube": {
   13.13 -    "message": "Bloquear propagandas dentro de vídeos do YouTube"
   13.14 -  }, 
   13.15    "cancel": {
   13.16      "description": "Rótulo para o botão de Cancelar", 
   13.17      "message": "Cancelar"
   13.18    }, 
   13.19    "clickhide_instructions": {
   13.20      "message": "Após o encerramento desta janela, clique (ou dê um clique com o botão direito) em um elemento da página."
   13.21    }, 
   13.22    "description": {
    14.1 --- a/_locales/ru/messages.json
    14.2 +++ b/_locales/ru/messages.json
    14.3 @@ -13,19 +13,16 @@
    14.4      "message": "Добавить фильтр(ы)?"
    14.5    }, 
    14.6    "add_your_own_filters": {
    14.7      "message": "Добавить свои фильтры"
    14.8    }, 
    14.9    "apply_changes": {
   14.10      "message": "Применить изменения"
   14.11    }, 
   14.12 -  "block_youtube": {
   14.13 -    "message": "Блокировать рекламу в видео на YouTube"
   14.14 -  }, 
   14.15    "cancel": {
   14.16      "description": "Cancel button label", 
   14.17      "message": "Отменить"
   14.18    }, 
   14.19    "clickhide_instructions": {
   14.20      "message": "После закрытия этого всплывающего окна щёлкните левой или правой кнопкой мыши элемент на странице."
   14.21    }, 
   14.22    "description": {
    15.1 --- a/_locales/sv/messages.json
    15.2 +++ b/_locales/sv/messages.json
    15.3 @@ -17,19 +17,16 @@
    15.4    }, 
    15.5    "apply_changes": {
    15.6      "message": "Verkställ ändringar"
    15.7    }, 
    15.8    "block_element": {
    15.9      "description": "Label for 'Block Element' context menu item", 
   15.10      "message": "Blockera objekt"
   15.11    }, 
   15.12 -  "block_youtube": {
   15.13 -    "message": "Blockera annonser i YouTube-videos"
   15.14 -  }, 
   15.15    "cancel": {
   15.16      "description": "Cancel button label", 
   15.17      "message": "Avbryt"
   15.18    }, 
   15.19    "clickhide_instructions": {
   15.20      "message": "När denna popup stängs, klicka (eller högerklicka) ett objekt på sidan."
   15.21    }, 
   15.22    "description": {
    16.1 --- a/_locales/vi/messages.json
    16.2 +++ b/_locales/vi/messages.json
    16.3 @@ -17,19 +17,16 @@
    16.4    }, 
    16.5    "apply_changes": {
    16.6      "message": "Lưu các thay đổi"
    16.7    }, 
    16.8    "block_element": {
    16.9      "description": "Label for 'Block Element' context menu item", 
   16.10      "message": "Khóa đối tượng này"
   16.11    }, 
   16.12 -  "block_youtube": {
   16.13 -    "message": "Chặn quảng cáo trong các đọan phim trên YouTube"
   16.14 -  }, 
   16.15    "cancel": {
   16.16      "description": "Cancel button label", 
   16.17      "message": "Hủy bỏ"
   16.18    }, 
   16.19    "clickhide_instructions": {
   16.20      "message": "Sau khi đóng của sổ này, hãy ấn chuột (hoặc ấn chuột phải) vào đối tượng mà bạn cần khóa trên trang."
   16.21    }, 
   16.22    "description": {
    17.1 --- a/_locales/zh_CN/messages.json
    17.2 +++ b/_locales/zh_CN/messages.json
    17.3 @@ -17,19 +17,16 @@
    17.4    }, 
    17.5    "apply_changes": {
    17.6      "message": "应用"
    17.7    }, 
    17.8    "block_element": {
    17.9      "description": "Label for 'Block Element' context menu item", 
   17.10      "message": "屏蔽此元素"
   17.11    }, 
   17.12 -  "block_youtube": {
   17.13 -    "message": "屏蔽YouTube视频中的广告"
   17.14 -  }, 
   17.15    "cancel": {
   17.16      "description": "Cancel button label", 
   17.17      "message": "取消"
   17.18    }, 
   17.19    "clickhide_instructions": {
   17.20      "message": "请点击(或右击)要屏蔽的元素"
   17.21    }, 
   17.22    "description": {
    18.1 --- a/_locales/zh_TW/messages.json
    18.2 +++ b/_locales/zh_TW/messages.json
    18.3 @@ -17,19 +17,16 @@
    18.4    }, 
    18.5    "apply_changes": {
    18.6      "message": "套用"
    18.7    }, 
    18.8    "block_element": {
    18.9      "description": "Label for 'Block Element' context menu item", 
   18.10      "message": "阻擋網頁元素"
   18.11    }, 
   18.12 -  "block_youtube": {
   18.13 -    "message": "阻擋 YouTube 影片廣告"
   18.14 -  }, 
   18.15    "cancel": {
   18.16      "description": "Cancel button label", 
   18.17      "message": "取消"
   18.18    }, 
   18.19    "clickhide_instructions": {
   18.20      "message": "此彈出訊息關閉後,請點選網頁上的元素。"
   18.21    }, 
   18.22    "description": {
    19.1 --- a/background.html
    19.2 +++ b/background.html
    19.3 @@ -8,18 +8,23 @@
    19.4  <script type="text/javascript" src="modules/FilterStorage.jsm"></script>
    19.5  <script type="text/javascript" src="modules/ElemHide.jsm"></script>
    19.6  <script type="text/javascript" src="modules/FilterListener.jsm"></script>
    19.7  <script type="text/javascript" src="modules/Matcher.jsm"></script>
    19.8  <script type="text/javascript" src="modules/Synchronizer.jsm"></script>
    19.9  <script type="text/javascript" src="lib/punycode.js"></script>
   19.10  <script type="text/javascript" src="lib/publicSuffixList.js"></script>
   19.11  <script type="text/javascript" src="lib/basedomain.js"></script>
   19.12 +<script type="text/javascript" src="webrequest.js"></script>
   19.13  
   19.14  <script type="text/javascript">
   19.15 +// Some types cannot be distinguished
   19.16 +RegExpFilter.typeMap.OBJECT_SUBREQUEST = RegExpFilter.typeMap.OBJECT;
   19.17 +RegExpFilter.typeMap.MEDIA = RegExpFilter.typeMap.FONT = RegExpFilter.typeMap.OTHER;
   19.18 +
   19.19  FilterListener.startup();
   19.20  Synchronizer.startup();
   19.21  
   19.22  window.addEventListener("unload", FilterListener.shutdown);
   19.23  
   19.24  FilterNotifier.addListener(function(action)
   19.25  {
   19.26    if (action == "load")
   19.27 @@ -120,21 +125,22 @@ function setDefaultOptions()
   19.28    {
   19.29      if(!(opt in localStorage))
   19.30        localStorage[opt] = val;
   19.31    }
   19.32  
   19.33    defaultOptionValue("shouldShowIcon", "true");
   19.34    defaultOptionValue("shouldShowBlockElementMenu", "true");
   19.35    defaultOptionValue("disableInlineTextAds", "true");
   19.36 -  defaultOptionValue("specialCaseYouTube", "true");
   19.37  
   19.38    // If user had older version installed, get rid of old option
   19.39 -  if("experimental" in localStorage)
   19.40 -    delete localStorage["experimental"];
   19.41 +  if ("specialCaseYouTube" in localStorage)
   19.42 +    delete localStorage.specialCaseYouTube;
   19.43 +  if ("experimental" in localStorage)
   19.44 +    delete localStorage.experimental;
   19.45  }
   19.46  
   19.47  // Upgrade options before we do anything else.
   19.48  setDefaultOptions(); 
   19.49  
   19.50  /**
   19.51   * Checks whether a page is whitelisted.
   19.52   * @param url {String}
   19.53 @@ -575,40 +581,12 @@ chrome.windows.getAll({populate: true}, 
   19.54  
   19.55  // Update icon if a tab changes location
   19.56  chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab)
   19.57  {
   19.58    chrome.tabs.sendRequest(tabId, {reqtype: "clickhide-deactivate"})
   19.59    if(changeInfo.status == "loading")
   19.60      refreshIconAndContextMenu(tab);
   19.61  });
   19.62 -
   19.63 -// Only load webrequest.js if we have the necessary permissions
   19.64 -var hasExperimentalPermissions = false;
   19.65 -var webRequest = null;
   19.66 -try
   19.67 -{
   19.68 -  var dummy = function(){};
   19.69 -  webRequest = "webRequest" in chrome ? chrome.webRequest : chrome.experimental.webRequest;
   19.70 -  webRequest.onBeforeRequest.addListener(dummy, {urls: []});
   19.71 -  webRequest.onBeforeRequest.removeListener(dummy);
   19.72 -  hasExperimentalPermissions = true;
   19.73 -
   19.74 -  // Some types cannot be distinguished
   19.75 -  RegExpFilter.typeMap.OBJECT_SUBREQUEST = RegExpFilter.typeMap.OBJECT;
   19.76 -  RegExpFilter.typeMap.MEDIA = RegExpFilter.typeMap.FONT = RegExpFilter.typeMap.OTHER;
   19.77 -}
   19.78 -catch (e) {}
   19.79 -
   19.80 -if (hasExperimentalPermissions)
   19.81 -{
   19.82 -  window.addEventListener("load", function()
   19.83 -  {
   19.84 -    var script = document.createElement("script");
   19.85 -    script.setAttribute("src", "webrequest.js");
   19.86 -    document.body.appendChild(script);
   19.87 -  }, false);
   19.88 -}
   19.89 -
   19.90  </script>
   19.91  
   19.92  </head>
   19.93  </html>
    20.1 --- a/build.py
    20.2 +++ b/build.py
    20.3 @@ -26,39 +26,28 @@ Options:
    20.4  
    20.5  def removeUpdateURL(zip, dir, fileName, fileData):
    20.6    if fileName == 'manifest.json':
    20.7      data = json.loads(fileData)
    20.8      del data['update_url']
    20.9      return json.dumps(data, sort_keys=True, indent=2)
   20.10    return fileData
   20.11  
   20.12 -def useExperimentalUpdateURL(zip, dir, fileName, fileData):
   20.13 +def setExperimentalSettings(zip, dir, fileName, fileData):
   20.14    if fileName == 'manifest.json':
   20.15      data = json.loads(fileData)
   20.16      if 'update_url' in data:
   20.17        index = data['update_url'].rfind('/')
   20.18        if index >= 0:
   20.19          data['update_url'] = data['update_url'][0:index] + '-experimental' + data['update_url'][index:]
   20.20 +    data['permissions'] += ['experimental']
   20.21      data['name'] += ' experimental build'
   20.22      return json.dumps(data, sort_keys=True, indent=2)
   20.23    return fileData
   20.24  
   20.25 -def removeExperimentalPermissions(zip, dir, fileName, fileData):
   20.26 -  if fileName == 'manifest.json':
   20.27 -    data = json.loads(fileData)
   20.28 -    data['permissions'] = filter(lambda p: p != 'experimental', data['permissions'])
   20.29 -    if 'content_scripts' in data:
   20.30 -      for script in data['content_scripts']:
   20.31 -        if 'js' in script:
   20.32 -          script['js'] = filter(lambda s: s != 'include.experimental.js', script['js'])
   20.33 -
   20.34 -    return json.dumps(data, sort_keys=True, indent=2)
   20.35 -  return fileData
   20.36 -
   20.37  def addBuildNumber(revision, zip, dir, fileName, fileData):
   20.38    if fileName == 'manifest.json':
   20.39      if not revision:
   20.40        revision, dummy = subprocess.Popen(['hg', '-R', dir, 'id', '-n'], stdin=subprocess.PIPE, stdout=subprocess.PIPE).communicate()
   20.41        revision = re.sub(r'\D', '', revision)
   20.42      if len(revision) > 0:
   20.43        data = json.loads(fileData)
   20.44        while data['version'].count('.') < 2:
   20.45 @@ -174,19 +163,17 @@ if __name__ == '__main__':
   20.46        allowExperimental = True
   20.47  
   20.48    filters = []
   20.49    if isRelease:
   20.50      filters.append(removeUpdateURL)
   20.51    else:
   20.52      filters.append(lambda zip, dir, fileName, fileData: addBuildNumber(buildNum, zip, dir, fileName, fileData))
   20.53      if allowExperimental:
   20.54 -      filters.append(useExperimentalUpdateURL)
   20.55 -  if not allowExperimental:
   20.56 -    filters.append(removeExperimentalPermissions)
   20.57 +      filters.append(setExperimentalSettings)
   20.58    filters.append(mergeContentScripts)
   20.59  
   20.60    zipdata = packDirectory(inputdir, filters)
   20.61    signature = None
   20.62    pubkey = None
   20.63    if keyfile != None:
   20.64      signature = signBinary(zipdata, keyfile)
   20.65      pubkey = getPublicKey(keyfile)
    21.1 deleted file mode 100644
    21.2 --- a/include.experimental.js
    21.3 +++ /dev/null
    21.4 @@ -1,8 +0,0 @@
    21.5 -/*
    21.6 - * This Source Code is subject to the terms of the Mozilla Public License
    21.7 - * version 2.0 (the "License"). You can obtain a copy of the License at
    21.8 - * http://mozilla.org/MPL/2.0/.
    21.9 - */
   21.10 -
   21.11 -// This file will be included in experimental builds only, this is merely a flag
   21.12 -var isExperimental = true;
    22.1 --- a/include.postload.js
    22.2 +++ b/include.postload.js
    22.3 @@ -1,16 +1,14 @@
    22.4  /*
    22.5   * This Source Code is subject to the terms of the Mozilla Public License
    22.6   * version 2.0 (the "License"). You can obtain a copy of the License at
    22.7   * http://mozilla.org/MPL/2.0/.
    22.8   */
    22.9  
   22.10 -var enabled = false; // Enabled for this particular domain.
   22.11 -
   22.12  // Click-to-hide stuff
   22.13  var clickHide_activated = false;
   22.14  var currentElement = null;
   22.15  var currentElement_boxShadow = null;
   22.16  var currentElement_backgroundColor;
   22.17  var clickHideFilters = null;
   22.18  var highlightedElementsSelector = null;
   22.19  var highlightedElementsBoxShadows = null;
   22.20 @@ -348,16 +346,79 @@ function getElementURL(elt) {
   22.21          url = params[0].getAttribute("value");
   22.22      }
   22.23    } else if(!url) {
   22.24      url = elt.getAttribute("src") || elt.getAttribute("href"); 
   22.25    }
   22.26    return url;
   22.27  }
   22.28  
   22.29 +// Converts relative to absolute URL
   22.30 +// e.g.: foo.swf on http://example.com/whatever/bar.html
   22.31 +//  -> http://example.com/whatever/foo.swf
   22.32 +function relativeToAbsoluteUrl(url)
   22.33 +{
   22.34 +  // If URL is already absolute, don't mess with it
   22.35 +  if (!url || /^[\w\-]+:/i.test(url))
   22.36 +    return url;
   22.37 +
   22.38 +  // Leading / means absolute path
   22.39 +  if(url[0] == '/')
   22.40 +    return document.location.protocol + "//" + document.location.host + url;
   22.41 +
   22.42 +  // Remove filename and add relative URL to it
   22.43 +  var base = document.baseURI.match(/.+\//);
   22.44 +  if(!base)
   22.45 +    return document.baseURI + "/" + url;
   22.46 +  return base[0] + url;
   22.47 +}
   22.48 +
   22.49 +// This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js
   22.50 +// and licensed under the MIT license. See jquery-*.min.js for details.
   22.51 +function removeDotSegments(u) {
   22.52 +  var r = '', m = [];
   22.53 +  if (/\./.test(u)) {
   22.54 +    while (u !== undefined && u !== '') {
   22.55 +      if (u === '.' || u === '..') {
   22.56 +        u = '';
   22.57 +      } else if (/^\.\.\//.test(u)) { // starts with ../
   22.58 +        u = u.substring(3);
   22.59 +      } else if (/^\.\//.test(u)) { // starts with ./
   22.60 +        u = u.substring(2);
   22.61 +      } else if (/^\/\.(\/|$)/.test(u)) { // starts with /./ or consists of /.
   22.62 +        u = '/' + u.substring(3);
   22.63 +      } else if (/^\/\.\.(\/|$)/.test(u)) { // starts with /../ or consists of /..
   22.64 +        u = '/' + u.substring(4);
   22.65 +        r = r.replace(/\/?[^\/]+$/, '');
   22.66 +      } else {
   22.67 +        m = u.match(/^(\/?[^\/]*)(\/.*)?$/);
   22.68 +        u = m[2];
   22.69 +        r = r + m[1];
   22.70 +      }
   22.71 +    }
   22.72 +    return r;
   22.73 +  } else {
   22.74 +    return u;
   22.75 +  }
   22.76 +}
   22.77 +
   22.78 +// Does some degree of URL normalization
   22.79 +function normalizeURL(url)
   22.80 +{
   22.81 +  var components = url.match(/(.+:\/\/.+?)\/(.*)/);
   22.82 +  if(!components)
   22.83 +    return url;
   22.84 +  var newPath = removeDotSegments(components[2]);
   22.85 +  if(newPath.length == 0)
   22.86 +    return components[1];
   22.87 +  if(newPath[0] != '/')
   22.88 +    newPath = '/' + newPath;
   22.89 +  return components[1] + newPath;
   22.90 +}
   22.91 +
   22.92  // Content scripts are apparently invoked on non-HTML documents, so we have to
   22.93  // check for that before doing stuff. |document instanceof HTMLDocument| check
   22.94  // will fail on some sites like planet.mozilla.org because WebKit creates
   22.95  // Document instances for XHTML documents, have to test the root element.
   22.96  if (document.documentElement instanceof HTMLElement)
   22.97  {
   22.98    // Use a contextmenu handler to save the last element the user right-clicked on.
   22.99    // To make things easier, we actually save the DOM event.
  22.100 @@ -440,27 +501,27 @@ if (document.documentElement instanceof 
  22.101        case "clickhide-new-filter":
  22.102          // The request is received by all frames, so ignore it if we're not the frame the
  22.103          // user right-clicked in
  22.104          if(!lastRightClickEvent)
  22.105            return;
  22.106          // We hope the URL we are given is the same as the one in the element referenced
  22.107          // by lastRightClickEvent.target. If not, we just discard
  22.108          var target = lastRightClickEvent.target;
  22.109 -        var url = relativeToAbsoluteUrl(target.src);
  22.110 +        var url = target.src;
  22.111          // If we don't have the element with a src URL same as the filter, look for it.
  22.112          // Chrome's context menu API is terrible. Why can't it give us the friggin' element
  22.113          // to start with?
  22.114          if(request.filter !== url) {
  22.115            // Grab all elements with a src attribute.
  22.116            // This won't work for all object/embed tags, but the context menu API doesn't
  22.117            // work on those, so we're OK for now.
  22.118            var elts = document.querySelectorAll('[src]');
  22.119            for(var i=0; i<elts.length; i++) {
  22.120 -            url = relativeToAbsoluteUrl(elts[i].src);
  22.121 +            url = elts[i].src;
  22.122              if(request.filter === url) {
  22.123                // This is hopefully our element. In case of multiple elements
  22.124                // with the same src, only one will be highlighted.
  22.125                target = elts[i];
  22.126                break;
  22.127              }
  22.128            }
  22.129          }
  22.130 @@ -481,24 +542,9 @@ if (document.documentElement instanceof 
  22.131          else
  22.132            console.log("clickhide-new-filter: URLs don't match. Couldn't find that element.", request.filter, url, lastRightClickEvent.target.src);
  22.133          break;
  22.134        default:
  22.135          sendResponse({});
  22.136          break;
  22.137      }
  22.138    });
  22.139 -
  22.140 -  if (isExperimental != true)
  22.141 -  {
  22.142 -    chrome.extension.sendRequest({reqtype: "get-domain-enabled-state"}, function(response)
  22.143 -    {
  22.144 -      enabled = response.enabled;
  22.145 -      if(enabled)
  22.146 -      {
  22.147 -        // Nuke background if it's an ad
  22.148 -        var bodyBackground = getComputedStyle(document.body).backgroundImage;
  22.149 -        if (bodyBackground && /^url\((.*)\)$/.test(bodyBackground) && shouldBlock(RegExp.$1, "IMAGE"))
  22.150 -          document.body.style.setProperty("background-image", "none", "important");
  22.151 -      }
  22.152 -    });
  22.153 -  }
  22.154  }
    23.1 --- a/include.preload.js
    23.2 +++ b/include.preload.js
    23.3 @@ -1,27 +1,14 @@
    23.4  /*
    23.5   * This Source Code is subject to the terms of the Mozilla Public License
    23.6   * version 2.0 (the "License"). You can obtain a copy of the License at
    23.7   * http://mozilla.org/MPL/2.0/.
    23.8   */
    23.9  
   23.10 -var isExperimental;
   23.11 -
   23.12 -var TagToType = {
   23.13 -  "SCRIPT": "SCRIPT",
   23.14 -  "IMG": "IMAGE",
   23.15 -  "LINK": "STYLESHEET",
   23.16 -  "OBJECT": "OBJECT",
   23.17 -  "EMBED": "OBJECT",
   23.18 -  "IFRAME": "SUBDOCUMENT"
   23.19 -};
   23.20 -
   23.21 -var hostDomain = null;
   23.22 -
   23.23  var SELECTOR_GROUP_SIZE = 20;
   23.24  
   23.25  var savedBeforeloadEvents = new Array();
   23.26  
   23.27  var elemhideElt = null;
   23.28  
   23.29  // Sets the currently used CSS rules for elemhide filters
   23.30  function setElemhideCSSRules(selectors)
   23.31 @@ -52,200 +39,25 @@ function setElemhideCSSRules(selectors)
   23.32      {
   23.33        var selector = selectors.slice(i, i + SELECTOR_GROUP_SIZE).join(", ");
   23.34        elt.sheet.insertRule(selector + " { display: none !important; }", j);
   23.35      }
   23.36    }
   23.37    setRules();
   23.38  }
   23.39  
   23.40 -// Hides a single element
   23.41 -function nukeSingleElement(elt) {
   23.42 -  if(elt.innerHTML)
   23.43 -    elt.innerHTML = "";
   23.44 -  if(elt.innerText)
   23.45 -    elt.innerText = "";
   23.46 -  elt.style.display = "none";
   23.47 -  elt.style.visibility = "hidden";
   23.48 -  // If this is a LINK tag, it's probably a stylesheet, so disable it. Actually removing
   23.49 -  // it seems to intermittently break page rendering.
   23.50 -  if(elt.localName && elt.localName.toUpperCase() == "LINK")
   23.51 -    elt.setAttribute("disabled", "");
   23.52 -}
   23.53 -
   23.54 -// This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js
   23.55 -// and licensed under the MIT license. See jquery-*.min.js for details.
   23.56 -function removeDotSegments(u) {
   23.57 -  var r = '', m = [];
   23.58 -  if (/\./.test(u)) {
   23.59 -    while (u !== undefined && u !== '') {
   23.60 -      if (u === '.' || u === '..') {
   23.61 -        u = '';
   23.62 -      } else if (/^\.\.\//.test(u)) { // starts with ../
   23.63 -        u = u.substring(3);
   23.64 -      } else if (/^\.\//.test(u)) { // starts with ./
   23.65 -        u = u.substring(2);
   23.66 -      } else if (/^\/\.(\/|$)/.test(u)) { // starts with /./ or consists of /.
   23.67 -        u = '/' + u.substring(3);
   23.68 -      } else if (/^\/\.\.(\/|$)/.test(u)) { // starts with /../ or consists of /..
   23.69 -        u = '/' + u.substring(4);
   23.70 -        r = r.replace(/\/?[^\/]+$/, '');
   23.71 -      } else {
   23.72 -        m = u.match(/^(\/?[^\/]*)(\/.*)?$/);
   23.73 -        u = m[2];
   23.74 -        r = r + m[1];
   23.75 -      }
   23.76 -    }
   23.77 -    return r;
   23.78 -  } else {
   23.79 -    return u;
   23.80 -  }
   23.81 -}
   23.82 -
   23.83 -// Does some degree of URL normalization
   23.84 -function normalizeURL(url)
   23.85 -{
   23.86 -  var components = url.match(/(.+:\/\/.+?)\/(.*)/);
   23.87 -  if(!components)
   23.88 -    return url;
   23.89 -  var newPath = removeDotSegments(components[2]);
   23.90 -  if(newPath.length == 0)
   23.91 -    return components[1];
   23.92 -  if(newPath[0] != '/')
   23.93 -    newPath = '/' + newPath;
   23.94 -  return components[1] + newPath;
   23.95 -}
   23.96 -
   23.97 -// Converts relative to absolute URL
   23.98 -// e.g.: foo.swf on http://example.com/whatever/bar.html
   23.99 -//  -> http://example.com/whatever/foo.swf
  23.100 -function relativeToAbsoluteUrl(url) {
  23.101 -  // If URL is already absolute, don't mess with it
  23.102 -  if(!url || url.match(/^http/i))
  23.103 -    return url;
  23.104 -  // Leading / means absolute path
  23.105 -  if(url[0] == '/') {
  23.106 -    return document.location.protocol + "//" + document.location.host + url;
  23.107 -  }
  23.108 -  // Remove filename and add relative URL to it
  23.109 -  var base = document.baseURI.match(/.+\//);
  23.110 -  if(!base)
  23.111 -    return document.baseURI + "/" + url;
  23.112 -  return base[0] + url;
  23.113 -}
  23.114 -
  23.115 -// Extracts a domain name from a URL
  23.116 -function extractDomainFromURL(url)
  23.117 -{
  23.118 -  if(!url)
  23.119 -    return "";
  23.120 -
  23.121 -  var x = url.substr(url.indexOf("://") + 3);
  23.122 -  x = x.substr(0, x.indexOf("/"));
  23.123 -  x = x.substr(x.indexOf("@") + 1);
  23.124 -  if (x.indexOf("[") == 0 && x.indexOf("]") > 0)
  23.125 -  {
  23.126 -    x = x.substring(1,x.indexOf("]"));
  23.127 -  }
  23.128 -  else
  23.129 -  {
  23.130 -    colPos = x.indexOf(":");
  23.131 -    if (colPos >= 0)
  23.132 -      x = x.substr(0, colPos);
  23.133 -  }
  23.134 -  return x;
  23.135 -}
  23.136 -
  23.137 -/**
  23.138 - * Checks whether a request is third party for the current document, uses
  23.139 - * our effective document domain as received by the background process.
  23.140 - */
  23.141 -function isThirdParty(requestHost)
  23.142 -{
  23.143 -  if (!hostDomain)
  23.144 -    return true;
  23.145 -
  23.146 -  // Remove trailing dots
  23.147 -  requestHost = requestHost.replace(/\.+$/, "");
  23.148 -
  23.149 -  if (requestHost.length > hostDomain.length)
  23.150 -    return (requestHost.substr(requestHost.length - hostDomain.length - 1) != "." + hostDomain);
  23.151 -  else
  23.152 -    return (requestHost != hostDomain);
  23.153 -}
  23.154 -
  23.155 -// This beforeload handler is used before we hear back from the background process about
  23.156 -// whether we're enabled etc. It saves the events so we can replay them to the normal
  23.157 -// beforeload handler once we know whether we're enabled - to catch ads that might have
  23.158 -// snuck by.
  23.159 -function saveBeforeloadEvent(e) {
  23.160 -  savedBeforeloadEvents.push(e);
  23.161 -}
  23.162 -
  23.163 -/**
  23.164 - * Tests whether a request needs to be blocked.
  23.165 - */
  23.166 -function shouldBlock(/**String*/ url, /**String*/ type)
  23.167 -{
  23.168 -  var url = relativeToAbsoluteUrl(url);
  23.169 -  var requestHost = extractDomainFromURL(url);
  23.170 -  var thirdParty = isThirdParty(requestHost);
  23.171 -  var match = defaultMatcher.matchesAny(url, type, window.location.hostname, thirdParty);
  23.172 -  return (match && match instanceof BlockingFilter);
  23.173 -}
  23.174 -
  23.175 -/**
  23.176 - * Responds to beforeload events by preventing load and nuking the element if
  23.177 - * it's an ad.
  23.178 - */
  23.179 -function beforeloadHandler(/**Event*/ e)
  23.180 -{
  23.181 -  if (shouldBlock(e.url, TagToType[e.target.localName.toUpperCase()]))
  23.182 -  {
  23.183 -    e.preventDefault();
  23.184 -    if (e.target)
  23.185 -      nukeSingleElement(e.target);
  23.186 -  }
  23.187 -}
  23.188 -
  23.189  function sendRequests()
  23.190  {
  23.191    // Make sure this is really an HTML page, as Chrome runs these scripts on just about everything
  23.192    if (!(document.documentElement instanceof HTMLElement))
  23.193      return;
  23.194  
  23.195 -  // Blocking from content script is unnecessary in experimental builds, it is
  23.196 -  // done though webRequest API.
  23.197 -  if (isExperimental != true)
  23.198 -  {
  23.199 -    chrome.extension.sendRequest({reqtype: "get-settings", matcher: true, host: window.location.hostname}, function(response)
  23.200 -    {
  23.201 -      document.removeEventListener("beforeload", saveBeforeloadEvent, true);
  23.202 -
  23.203 -      if (response.enabled)
  23.204 -      {
  23.205 -        hostDomain = response.hostDomain;
  23.206 -        defaultMatcher.fromCache(JSON.parse(response.matcherData));
  23.207 -
  23.208 -        document.addEventListener("beforeload", beforeloadHandler, true);
  23.209 -
  23.210 -        // Replay the events that were saved while we were waiting to learn whether we are enabled
  23.211 -        for(var i = 0; i < savedBeforeloadEvents.length; i++)
  23.212 -          beforeloadHandler(savedBeforeloadEvents[i]);
  23.213 -      }
  23.214 -      delete savedBeforeloadEvents;
  23.215 -    });
  23.216 -  }
  23.217 -
  23.218    chrome.extension.sendRequest({reqtype: "get-settings", selectors: true, host: window.location.hostname}, function(response)
  23.219    {
  23.220      setElemhideCSSRules(response.selectors);
  23.221    });
  23.222  }
  23.223  
  23.224 -if (isExperimental != true)
  23.225 -  document.addEventListener("beforeload", saveBeforeloadEvent, true);
  23.226 -
  23.227  // In Chrome 18 the document might not be initialized yet
  23.228  if (document.documentElement)
  23.229    sendRequests();
  23.230  else
  23.231    window.setTimeout(sendRequests, 0);
    24.1 deleted file mode 100644
    24.2 --- a/include.youtube.js
    24.3 +++ /dev/null
    24.4 @@ -1,74 +0,0 @@
    24.5 -/*
    24.6 - * This Source Code is subject to the terms of the Mozilla Public License
    24.7 - * version 2.0 (the "License"). You can obtain a copy of the License at
    24.8 - * http://mozilla.org/MPL/2.0/.
    24.9 - */
   24.10 -
   24.11 -var isExperimental;
   24.12 -
   24.13 -// Don't do anything in experimental builds, webRequest API will handle this
   24.14 -if (isExperimental == true)
   24.15 -  return;
   24.16 -
   24.17 -// YouTube special case option
   24.18 -var shouldRemoveYouTubeAds = undefined;
   24.19 -var savedPlayer, savedPlayerVars;
   24.20 -
   24.21 -function stripYouTubePlayerAds(player, newVars)
   24.22 -{
   24.23 -  player.setAttribute("flashvars", newVars.join("&"));
   24.24 -
   24.25 -  // Remove the node and insert it back, the variables won't be reloaded otherwise
   24.26 -  var parent = player.parentNode;
   24.27 -  var insertBefore = player.nextSibling;
   24.28 -  parent.removeChild(player);
   24.29 -  parent.insertBefore(player, insertBefore);
   24.30 -}
   24.31 -
   24.32 -function onYouTubeBeforeLoad(e)
   24.33 -{
   24.34 -  var eltDomain = extractDomainFromURL(e.url);
   24.35 -  var player = e.target;
   24.36 -  if (player && /\bytimg\.com$/.test(eltDomain) &&
   24.37 -      /^(embed|object)$/.test(player.localName) &&
   24.38 -      player.hasAttribute("flashvars"))
   24.39 -  {
   24.40 -    // Remove a bunch of known parameters from flashvars attribute of the player
   24.41 -    var flashVars = player.getAttribute("flashvars").split("&");
   24.42 -    var newVars = [];
   24.43 -    for (var i = 0; i < flashVars.length; i++)
   24.44 -      if (!/^(ad\d*_|instream|infringe|invideo|interstitial|mpu|prerolls|tpas_ad_type_id|trueview|watermark)/.test(flashVars[i]))
   24.45 -        newVars.push(flashVars[i]);
   24.46 -    if (newVars.length != flashVars.length)
   24.47 -    {
   24.48 -      if (typeof shouldRemoveYouTubeAds == "undefined")
   24.49 -      {
   24.50 -        // If enabled-check hasn't returned yet, save the event and new flashvars so that ad removal
   24.51 -        // can occur when it does return. We ought only to need to save one since there will only be
   24.52 -        // one video player loaded at a time.
   24.53 -        savedPlayer = player;
   24.54 -        savedPlayerVars = newVars;
   24.55 -      }
   24.56 -      else if (shouldRemoveYouTubeAds)
   24.57 -        stripYouTubePlayerAds(player, newVars);
   24.58 -    }
   24.59 -  }
   24.60 -}
   24.61 -
   24.62 -// Ask the backend whether we are enabled. This may take a while, so we attach the beforeload listener
   24.63 -// no matter what. If this callback hasn't been invoked by the time we need to act on the YouTube
   24.64 -// player object, the beforeload handler will just save the target object and new flashvars so that
   24.65 -// this callback can modify the flashvars and reload the object.
   24.66 -chrome.extension.sendRequest({reqtype: "get-domain-enabled-state"}, function(response)
   24.67 -{
   24.68 -  shouldRemoveYouTubeAds = (response.enabled && response.specialCaseYouTube);
   24.69 -  if (shouldRemoveYouTubeAds)
   24.70 -  {
   24.71 -    if (savedPlayer)
   24.72 -      stripYouTubePlayerAds(savedPlayer, savedPlayerVars);
   24.73 -  }
   24.74 -  else
   24.75 -    document.removeEventListener("beforeload", onYouTubeBeforeLoad, true);
   24.76 -});
   24.77 -
   24.78 -document.addEventListener("beforeload", onYouTubeBeforeLoad, true);
    25.1 --- a/manifest.json
    25.2 +++ b/manifest.json
    25.3 @@ -1,41 +1,35 @@
    25.4  {
    25.5    "name": "__MSG_name__",
    25.6    "version": "1.2",
    25.7 -  "minimum_chrome_version": "16.0",
    25.8 +  "minimum_chrome_version": "17.0",
    25.9    "description": "__MSG_description__",
   25.10    "default_locale": "en",
   25.11    "update_url": "https://adblockplus.org/devbuilds/adblockpluschrome/updates.xml",
   25.12    "page_action": {
   25.13      "default icon": "icons/abp-19.png",
   25.14      "default title": "Adblock Plus",
   25.15      "popup": "popup.html"
   25.16    },
   25.17    "icons": {
   25.18      "16": "icons/abp-16.png",
   25.19      "32": "icons/abp-32.png",
   25.20      "48": "icons/abp-48.png",
   25.21      "128": "icons/abp-128.png"
   25.22    },
   25.23    "permissions": [
   25.24 -    "tabs", "http://*/*", "https://*/*", "contextMenus", "webRequest", "webRequestBlocking", "unlimitedStorage", "experimental"
   25.25 +    "tabs", "http://*/*", "https://*/*", "contextMenus", "webRequest", "webRequestBlocking", "unlimitedStorage"
   25.26    ],
   25.27    "background_page": "background.html",
   25.28    "options_page": "options.html",
   25.29    "content_scripts": [
   25.30      {
   25.31 -      "matches": ["http://*.youtube.com/*", "https://*.youtube.com/*", "http://*.youtube-nocookie.com/*", "https://*.youtube-nocookie.com/*"],
   25.32 -      "js": ["include.experimental.js", "include.youtube.js"],
   25.33 -      "run_at": "document_start",
   25.34 -      "all_frames": true
   25.35 -    },
   25.36 -    {
   25.37        "matches": ["http://*/*", "https://*/*"],
   25.38 -      "js": ["modules/patches.js", "modules/FilterClasses.jsm", "modules/Matcher.jsm", "include.experimental.js", "include.preload.js"],
   25.39 +      "js": ["include.preload.js"],
   25.40        "run_at": "document_start",
   25.41        "all_frames": true
   25.42      },
   25.43      {
   25.44        "matches": ["http://*/*", "https://*/*"],
   25.45        "js": ["include.postload.js", "include.textads.js"],
   25.46        "run_at": "document_end",
   25.47        "all_frames": true
    26.1 --- a/options.html
    26.2 +++ b/options.html
    26.3 @@ -88,37 +88,31 @@ p {
    26.4  }
    26.5  
    26.6  </style>
    26.7  <script type="text/javascript" charset="utf-8">
    26.8  
    26.9  var backgroundPage = chrome.extension.getBackgroundPage();
   26.10  var imports = ["FilterStorage", "FilterNotifier", "Subscription", "SpecialSubscription",
   26.11                 "DownloadableSubscription", "Filter", "WhitelistFilter",
   26.12 -               "Synchronizer", "Utils", "hasExperimentalPermissions"];
   26.13 +               "Synchronizer", "Utils"];
   26.14  for (var i = 0; i < imports.length; i++)
   26.15    window[imports[i]] = backgroundPage[imports[i]];
   26.16  
   26.17  // Loads options from localStorage and sets UI elements accordingly
   26.18  function loadOptions()
   26.19  {
   26.20    FilterNotifier.addListener(onFilterChange);
   26.21  
   26.22    // Popuplate option checkboxes
   26.23    initCheckbox("shouldShowIcon");
   26.24    initCheckbox("shouldShowBlockElementMenu");
   26.25    initCheckbox("disableInlineTextAds");
   26.26 -  initCheckbox("specialCaseYouTube");
   26.27    initCheckbox("hidePlaceholders");
   26.28  
   26.29 -  if (hasExperimentalPermissions)
   26.30 -    document.getElementById("specialCaseYouTubeContainer").style.display = "none";
   26.31 -  else
   26.32 -    document.getElementById("hidePlaceholdersContainer").style.display = "none";
   26.33 -
   26.34    // Load recommended subscriptions
   26.35    loadRecommendations();
   26.36  
   26.37    // Show user's filters
   26.38    reloadFilters();
   26.39  }
   26.40  
   26.41  // Reloads the displayed subscriptions and filters
   26.42 @@ -765,19 +759,16 @@ document.title = chrome.i18n.getMessage(
   26.43          <input type="checkbox" id="shouldShowIcon" /><span class="i18n_show_icon"></span>
   26.44        </div>
   26.45        <div id="shouldShowBlockElementMenuContainer">
   26.46          <input type="checkbox" id="shouldShowBlockElementMenu" /><span class="i18n_show_block_element_menu"></span>
   26.47        </div>
   26.48        <div id="disableInlineTextAdsContainer">
   26.49          <input type="checkbox" id="disableInlineTextAds" /><span class="i18n_disable_inline"></span>
   26.50        </div>
   26.51 -      <div id="specialCaseYouTubeContainer">
   26.52 -        <input type="checkbox" id="specialCaseYouTube" /><span class="i18n_block_youtube"></span>
   26.53 -      </div>
   26.54        <div id="hidePlaceholdersContainer">
   26.55          <input type="checkbox" id="hidePlaceholders" /><span class="i18n_overlay_hideplaceholders_label"></span>
   26.56        </div>
   26.57      </p>
   26.58  
   26.59      <p class="i18n_found_a_bug">"https://adblockplus.org/forum/viewforum.php?f=10"</p>
   26.60    </div>
   26.61  </div>
    27.1 --- a/update_locales.py
    27.2 +++ b/update_locales.py
    27.3 @@ -117,16 +117,17 @@ if __name__ == '__main__':
    27.4      'global_synchronize_invalid_data',
    27.5      'global_synchronize_checksum_mismatch',
    27.6      'settings_enabled_column',
    27.7      'settings_remove_label',
    27.8      'settings_addsubscription_label',
    27.9      'subscriptionSelection_addSubscription_label',
   27.10      'subscriptionSelection_other_label',
   27.11      'hide_placeholders',
   27.12 +    'block_youtube',
   27.13    ]
   27.14    imported = [
   27.15      'global.properties subscription_invalid_location',
   27.16      'global.properties remove_subscription_warning',
   27.17      'overlay.dtd hideplaceholders.label',
   27.18      'filters.dtd subscription.lastDownload.inProgress',
   27.19      'filters.dtd subscription.lastDownload.invalidURL',
   27.20      'filters.dtd subscription.lastDownload.connectionError',
    28.1 --- a/webrequest.js
    28.2 +++ b/webrequest.js
    28.3 @@ -1,17 +1,17 @@
    28.4  /*
    28.5   * This Source Code is subject to the terms of the Mozilla Public License
    28.6   * version 2.0 (the "License"). You can obtain a copy of the License at
    28.7   * http://mozilla.org/MPL/2.0/.
    28.8   */
    28.9  
   28.10 -webRequest.onBeforeRequest.addListener(onBeforeRequest, {urls: ["http://*/*", "https://*/*"]}, ["blocking"]);
   28.11 -webRequest.onBeforeSendHeaders.addListener(onBeforeSendHeaders, {urls: ["http://*/*", "https://*/*"]}, ["requestHeaders", "blocking"]);
   28.12 -webRequest.onErrorOccurred.addListener(onErrorOccurred, {urls: ["http://*/*", "https://*/*"]});
   28.13 +chrome.webRequest.onBeforeRequest.addListener(onBeforeRequest, {urls: ["http://*/*", "https://*/*"]}, ["blocking"]);
   28.14 +chrome.webRequest.onBeforeSendHeaders.addListener(onBeforeSendHeaders, {urls: ["http://*/*", "https://*/*"]}, ["requestHeaders", "blocking"]);
   28.15 +chrome.webRequest.onErrorOccurred.addListener(onErrorOccurred, {urls: ["http://*/*", "https://*/*"]});
   28.16  chrome.tabs.onRemoved.addListener(forgetTab);
   28.17  
   28.18  var frames = {};
   28.19  var tabs = {};
   28.20  
   28.21  function onBeforeRequest(details)
   28.22  {
   28.23    var type = details.type;