home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2012 January / maximum-cd-2012-01.iso / DiscContents / digsby_setup.exe / lib / gui / imwin / imwin_ads.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2011-10-05  |  21.6 KB  |  631 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  3.  
  4. import sys
  5. import traceback
  6. import wx
  7. import cgui
  8. import simplejson
  9. import random
  10. from time import time
  11. from gui.browser.webkit import WebKitWindow
  12. from common import pref, profile
  13. from util.primitives.funcs import Delegate
  14. from logging import getLogger
  15. log = getLogger('imwin_ads')
  16. from util.net import UrlQuery
  17. AD_COOKIE_CLEAR_MINS = 60
  18. IMFRAME_MINSIZE = (320, 220)
  19. IMFRAME_WITH_AD_MINSIZE_H = (490, 350)
  20. IMFRAME_WITH_AD_MINSIZE_V = (320, 397)
  21. SHOULD_ROTATE = True
  22. PREF_FLASH_DISABLED = 'imwin.ads_disable_flash'
  23. CAMPAIGNS = {
  24.     'tagged': 'http://www.tagged.com/digsbytag.html',
  25.     'rubicon': 'http://serve.digsby.com/rubicon.html',
  26.     'rubicon_vertical': 'http://serve.digsby.com/rubicon2.html' }
  27.  
  28. def get_ad_campagin():
  29.     if _adposition() in ('left', 'right'):
  30.         return 'rubicon_vertical'
  31.     return 'rubicon'
  32.  
  33. PREF_AD_POSITION = 'imwin.ads_position'
  34.  
  35. def _adposition():
  36.     return pref(PREF_AD_POSITION, default = 'bottom')
  37.  
  38. PREF_ADS_ENABLED = 'imwin.ads'
  39.  
  40. def _adsenabled():
  41.     return pref(PREF_ADS_ENABLED, default = False)
  42.  
  43. AD_PANEL_MINSIZE_H = (466, 58)
  44. AD_PANEL_MINSIZE_V = (-1, -1)
  45. AD_PANEL_MAXSIZE_H = (728, 90)
  46. AD_PANEL_MAXSIZE_V = (160, 600)
  47. allowed_trigger_modes = ('focus', 'sendim')
  48. allowed_time_modes = ('real', 'engagement')
  49. ad_scenarios = [
  50.     (120, 'real', 'focus')]
  51.  
  52. def choose_ad_scenario():
  53.     s = ad_scenarios[:]
  54.     random.shuffle(s)
  55.     return s[0]
  56.  
  57.  
  58. class AdRotater(object):
  59.     
  60.     def __repr__(self):
  61.         ImFrame = ImFrame
  62.         import gui.imwin.imtabs
  63.         return '<AdRotater (secs=%s, time_mode=%s, trigger_mode=%s, has_focus=%r, idle=%r) (%.02f secs engagement)>' % (self.timer_secs, self.time_mode, self.trigger_mode, self.has_focus, ImFrame.engage_is_idle, self._engagement())
  64.  
  65.     
  66.     def __init__(self, timer_secs, time_mode, trigger_mode, current_time_func = time):
  67.         self.has_focus = False
  68.         self.timer_secs = timer_secs
  69.         self.time_mode = time_mode
  70.         self.trigger_mode = trigger_mode
  71.         self.scenario_identifier = '%s_%s_%s' % (timer_secs, time_mode, trigger_mode)
  72.         self._get_time = current_time_func
  73.         self._reset_time(start = False)
  74.         self.on_reload = Delegate()
  75.         if self.trigger_mode == 'focus':
  76.             self.wx_timer = wx.PyTimer(self._on_wxtimer)
  77.             self.wx_timer.StartRepeating(1000)
  78.         
  79.  
  80.     
  81.     def _on_wxtimer(self):
  82.         if not self.has_focus:
  83.             return None
  84.         if self.time_mode == 'engagement' or not (self.timer.paused) or self.time_mode == 'real':
  85.             self.trigger_event('focus')
  86.         
  87.  
  88.     
  89.     def trigger_event(self, event):
  90.         if self.should_rotate(event):
  91.             self.on_reload()
  92.         
  93.  
  94.     
  95.     def should_rotate(self, trigger_event):
  96.         if not SHOULD_ROTATE:
  97.             return False
  98.         ImFrame = ImFrame
  99.         import gui.imwin.imtabs
  100.         if ImFrame.engage_is_idle:
  101.             return False
  102.         if self.trigger_mode != trigger_event:
  103.             return False
  104.         if not self._enough_time_elapsed():
  105.             return False
  106.         return True
  107.  
  108.     
  109.     def pause(self):
  110.         if self.time_mode == 'engagement':
  111.             return self.timer.pause()
  112.  
  113.     
  114.     def unpause(self):
  115.         if self.time_mode == 'engagement':
  116.             return self.timer.unpause()
  117.  
  118.     
  119.     def _reset_time(self, start = True):
  120.         self.timer = Timer(get_time_func = self._get_time)
  121.         if start:
  122.             self.timer.start()
  123.         
  124.  
  125.     
  126.     def _engagement(self):
  127.         return self.timer.get_ticks()
  128.  
  129.     
  130.     def _enough_time_elapsed(self):
  131.         return self._engagement() >= self.timer_secs
  132.  
  133.  
  134. _ad_scenario = None
  135.  
  136. def ad_scenario():
  137.     global _ad_scenario
  138.     if _ad_scenario is None:
  139.         _ad_scenario = choose_ad_scenario()
  140.     
  141.     return _ad_scenario
  142.  
  143.  
  144. class AdPanel(WebKitWindow):
  145.     
  146.     def __init__(self, parent, rotater):
  147.         self.rotater = rotater
  148.         self.refresh_campaign()
  149.         WebKitWindow.__init__(self, parent, simple_events = True)
  150.         self._update_flash_enabled()
  151.         profile.prefs.add_gui_observer(self._update_flash_enabled, PREF_FLASH_DISABLED)
  152.         self.set_jsqueue_enabled(False)
  153.         self.set_window_open_redirects_to_browser(self._url_callback)
  154.         self.SetMinimumFontSize(10)
  155.         self._navigated_to_base_url = False
  156.         self.Bind(wx.webview.EVT_WEBVIEW_BEFORE_LOAD, self.OnBeforeLoad)
  157.         self.Bind(wx.webview.EVT_WEBVIEW_LOAD, self.on_loading)
  158.         self.update_minsize()
  159.         setup_webview_logging = setup_webview_logging
  160.         import gui.browser.webkit
  161.         jslog = getLogger('imwin_ads_js')
  162.         setup_webview_logging(self, jslog)
  163.         self._did_notify_click = False
  164.         self.SetFineGrainedResourceEvents(True)
  165.  
  166.     
  167.     def update_minsize(self):
  168.         if _adposition() in ('left', 'right'):
  169.             self.SetMinSize(AD_PANEL_MINSIZE_V)
  170.             self.SetMaxSize(AD_PANEL_MAXSIZE_V)
  171.         else:
  172.             self.SetMinSize(AD_PANEL_MINSIZE_H)
  173.             self.SetMaxSize(AD_PANEL_MAXSIZE_H)
  174.  
  175.     
  176.     def refresh_campaign(self):
  177.         campaign = get_ad_campagin()
  178.         self.ad_url_base = CAMPAIGNS[campaign]
  179.         old_ad_url = getattr(self, 'ad_url', None)
  180.         self.ad_url = UrlQuery(self.ad_url_base, utm_source = 'digsby_client', utm_medium = 'im_window', utm_content = self.rotater.scenario_identifier, utm_campaign = campaign)
  181.         if old_ad_url is not None and old_ad_url != self.ad_url:
  182.             self._reload_ad()
  183.         
  184.  
  185.     
  186.     def _update_flash_enabled(self, *a):
  187.         if not wx.IsDestroyed(self):
  188.             flash_enabled = not pref(PREF_FLASH_DISABLED, default = False)
  189.             self.WebSettings.SetPluginsEnabled(flash_enabled)
  190.         
  191.  
  192.     
  193.     def URL(self):
  194.         return self.RunScript('window.location.href')
  195.  
  196.     URL = property(URL)
  197.     
  198.     def on_loading(self, e):
  199.         
  200.         try:
  201.             url = self.URL
  202.         except wx.PyDeadObjectError:
  203.             return e.Skip()
  204.  
  205.         if not url or e.State != wx.webview.WEBVIEW_LOAD_TRANSFERRING:
  206.             return e.Skip()
  207.         at_base = url.startswith(self.ad_url_base)
  208.         if at_base:
  209.             self._navigated_to_base_url = True
  210.         
  211.         hijacked_url = getattr(self, '_did_hijack_url', None)
  212.         if not at_base and not (self._navigated_to_base_url):
  213.             log.info('loading blank window b/c caught possible proxy block to url %r', self.ad_url)
  214.             self.LoadURL('about:blank')
  215.         elif not at_base and self._navigated_to_base_url:
  216.             if hijacked_url is None or not urls_have_same_domain(url, hijacked_url):
  217.                 self._did_hijack_url = url
  218.                 log.warning('!!!! escaped from serve.digsby.com: %r', url)
  219.                 self._url_callback(url)
  220.                 self.RefreshAd()
  221.             
  222.  
  223.     
  224.     def _url_callback(self, url):
  225.         wx.LaunchDefaultBrowser(url)
  226.         self.notify_click(url)
  227.  
  228.     
  229.     def _is_double_url_call(self, url):
  230.         last = getattr(self, '_last_url_launched', None)
  231.         new = (url, time())
  232.         if last is not None and url == last[0]:
  233.             if abs(new[1] - last[1]) < 200:
  234.                 return True
  235.         
  236.         self._last_url_launched = new
  237.  
  238.     
  239.     def OnBeforeLoad(self, e):
  240.         url = e.URL
  241.         skip = True
  242.         if e.NavigationType == wx.webview.WEBVIEW_NAV_LINK_CLICKED:
  243.             e.Cancel()
  244.             self._url_callback(url)
  245.             skip = False
  246.         elif e.NavigationType == wx.webview.WEBVIEW_NAV_OTHER:
  247.             if not _debug_ads():
  248.                 self._log_ad_url(url)
  249.             
  250.         elif e.NavigationType == wx.webview.WEBVIEW_NAV_REQUEST:
  251.             url = e.URL
  252.             if self._should_blacklist_ad_url(url):
  253.                 log.info('ad URL BLACKLISTED, cancelling request %s', url)
  254.                 e.Cancel()
  255.                 skip = False
  256.             elif _debug_ads():
  257.                 self._log_ad_url(url)
  258.             
  259.         
  260.         e.Skip(skip)
  261.  
  262.     
  263.     def _log_ad_url(self, url):
  264.         last = getattr(self, '_last_logged_url', None)
  265.         if last is not None and last == url:
  266.             del self._last_logged_url
  267.         else:
  268.             log.info('ad URL %s', url)
  269.             self._last_logged_url = url
  270.  
  271.     blacklisted_urls = set(('http://qnet.hit.gemius.pl/pp_gemius.js',))
  272.     
  273.     def _should_blacklist_ad_url(self, url):
  274.         if url in self.blacklisted_urls:
  275.             return True
  276.         return False
  277.  
  278.     
  279.     def _reload_ad(self):
  280.         self._did_notify_click = False
  281.         self.rotater._reset_time()
  282.         log.info('Loading ad URL: %r', self.ad_url)
  283.         self._navigated_to_base_url = False
  284.         self.LoadURL(self.ad_url)
  285.  
  286.     
  287.     def notify_click(self, url):
  288.         if self._did_notify_click:
  289.             return None
  290.         self._did_notify_click = True
  291.         log.info('notifying ad click: %r', url)
  292.         self._track_analytics_event('click')
  293.  
  294.     
  295.     def _track_analytics_event(self, action):
  296.         script = '_gaq.push(%s);' % simplejson.dumps([
  297.             '_trackEvent',
  298.             self.rotater.scenario_identifier,
  299.             action])
  300.         print script
  301.         result = self.RunScript(script)
  302.         print 'RESULT', result
  303.  
  304.  
  305. GLASS_TRANSPARENT_COLOR = (0, 0, 0)
  306.  
  307. glass = lambda : if cgui.isGlassEnabled():
  308. passpref('imwin.ads_glass', default = True)
  309.  
  310. def construct_ad_panel(self, mainPanel, new_tab_cb, bind_pref = True):
  311.     if bind_pref:
  312.         
  313.         def on_ad_pref(src, attr, old, new):
  314.             ap = getattr(self, 'ad_panel', None)
  315.  
  316.         profile.prefs.add_gui_observer(on_ad_pref, PREF_ADS_ENABLED, obj = self)
  317.     
  318.     if not _adsenabled():
  319.         return None
  320.     should_clear_cookies = setup_cookie_timer(self)
  321.     adpos = _adposition()
  322.     borderSize = 1
  323.     extra_top = 8
  324.     rotater = AdRotater(*ad_scenario())
  325.     self._ad_rotater = rotater
  326.     self.on_engaged_start += rotater.unpause
  327.     self.on_engaged_end += rotater.pause
  328.     
  329.     def on_message(mode, imwin_ctrl):
  330.         if mode == 'im':
  331.             rotater.trigger_event('sendim')
  332.         
  333.  
  334.     self.on_sent_message += on_message
  335.     self._did_show_ad = False
  336.     
  337.     def check_focus():
  338.         if wx.IsDestroyed(self):
  339.             return None
  340.         if self.IsActive():
  341.             pass
  342.         rotater.has_focus = not self.IsIconized()
  343.         if rotater.has_focus:
  344.             if not self._did_show_ad:
  345.                 self._did_show_ad = True
  346.                 rotater.on_reload()
  347.             else:
  348.                 rotater.trigger_event('focus')
  349.         
  350.  
  351.     wx.CallLater(50, check_focus)
  352.     
  353.     def on_iconize(e):
  354.         e.Skip()
  355.         wx.CallAfter(check_focus)
  356.  
  357.     
  358.     def on_activate(e):
  359.         e.Skip()
  360.         wx.CallAfter(check_focus)
  361.         if not glass():
  362.             self.Refresh()
  363.         
  364.  
  365.     self.Bind(wx.EVT_ACTIVATE, on_activate)
  366.     self.Bind(wx.EVT_ICONIZE, on_iconize)
  367.     horiz_padding = 8
  368.     extra_horizontal = 1
  369.     
  370.     def build_ad_sizer(adpos = None, layout_now = (None, None, None, None if should_clear_cookies else _adsenabled(), (self, (((self,), self),)), None, True)):
  371.         if wx.IsDestroyed(self):
  372.             return None
  373.         enabled = _adsenabled()
  374.         if adpos is None:
  375.             adpos = _adposition()
  376.         
  377.         self.Frozen().__enter__()
  378.         
  379.         try:
  380.             self.SetSizer(None)
  381.             if not enabled:
  382.                 minsize = IMFRAME_MINSIZE
  383.             elif adpos in ('left', 'right'):
  384.                 minsize = IMFRAME_WITH_AD_MINSIZE_V
  385.             else:
  386.                 minsize = IMFRAME_WITH_AD_MINSIZE_H
  387.             self.SetMinSize(minsize)
  388.             if enabled:
  389.                 ad_panel.Show()
  390.             
  391.             if not enabled:
  392.                 ad_panel.Hide()
  393.                 sz = wx.BoxSizer(wx.VERTICAL)
  394.                 sz.Add(mainPanel, 1, wx.EXPAND)
  395.             elif adpos == 'top':
  396.                 sz = wx.BoxSizer(wx.VERTICAL)
  397.                 sz.Add((borderSize, borderSize))
  398.                 sz.Add(ad_panel, 0, wx.ALIGN_CENTER_HORIZONTAL)
  399.                 sz.Add((borderSize, borderSize + extra_top))
  400.                 sz.Add(mainPanel, 1, wx.EXPAND)
  401.             elif adpos == 'left':
  402.                 sz = wx.BoxSizer(wx.HORIZONTAL)
  403.                 sz.Add((extra_horizontal, 1))
  404.                 sz.Add(ad_panel, 0, wx.ALIGN_CENTER_VERTICAL)
  405.                 sz.Add((horiz_padding, 1))
  406.                 sz.Add(mainPanel, 1, wx.EXPAND)
  407.             elif adpos == 'right':
  408.                 sz = wx.BoxSizer(wx.HORIZONTAL)
  409.                 sz.Add(mainPanel, 1, wx.EXPAND)
  410.                 sz.Add((horiz_padding, borderSize))
  411.                 sz.Add(ad_panel, 0, wx.ALIGN_CENTER_VERTICAL)
  412.                 sz.Add((extra_horizontal, 1))
  413.             else:
  414.                 sz = wx.BoxSizer(wx.VERTICAL)
  415.                 sz.Add(mainPanel, 1, wx.EXPAND)
  416.                 sz.Add((borderSize, borderSize + extra_top))
  417.                 sz.Add(ad_panel, 0, wx.ALIGN_CENTER_HORIZONTAL)
  418.                 sz.Add((borderSize, borderSize))
  419.             self.SetSizer(sz)
  420.             if layout_now:
  421.                 self.Layout()
  422.         finally:
  423.             pass
  424.  
  425.  
  426.     build_ad_sizer(adpos, layout_now = False)
  427.     self.build_ad_sizer = build_ad_sizer
  428.     
  429.     def on_pref_change(src, attr, old, new):
  430.         if wx.IsDestroyed(self):
  431.             return None
  432.         build_ad_sizer(_adposition())
  433.         ad_panel.update_minsize()
  434.         on_resize()
  435.         ad_panel.refresh_campaign()
  436.  
  437.     profile.prefs.add_gui_observer(on_pref_change, PREF_AD_POSITION, obj = self)
  438.     if 'wxMSW' in wx.PlatformInfo:
  439.         get_frame_color = get_frame_color
  440.         import gui.native.win.winutil
  441.     else:
  442.         
  443.         get_frame_color = lambda active: wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)
  444.     
  445.     def paint(e):
  446.         r = mainPanel.Rect
  447.         (x, y) = r.BottomLeft
  448.         x += (r.Width - x) / 2 - ad_panel.Size.width / 2
  449.         dc = wx.AutoBufferedPaintDC(self)
  450.         dc.Pen = wx.TRANSPARENT_PEN
  451.         if glass():
  452.             dc.Brush = wx.Brush(wx.Color(*GLASS_TRANSPARENT_COLOR))
  453.         else:
  454.             dc.Brush = wx.Brush(get_frame_color(self.IsActive()))
  455.         dc.DrawRectangleRect(self.ClientRect)
  456.         if not _adsenabled():
  457.             if glass():
  458.                 cgui.glassExtendInto(self, 0, 0, 0, 0)
  459.             
  460.             return None
  461.  
  462.     self.Bind(wx.EVT_PAINT, paint)
  463.     
  464.     def _ad_panel_shown():
  465.         ad_panel = getattr(self, 'ad_panel', None)
  466.         if ad_panel is not None:
  467.             return ad_panel.IsShown()
  468.  
  469.     
  470.     def on_resize(e = (None, ((None, None, None, None, None, None, None, None),), None)):
  471.         if hasattr(e, 'Skip'):
  472.             e.Skip()
  473.         
  474.         if wx.IsDestroyed(self) or not _ad_panel_shown():
  475.             return None
  476.         if _adposition() in ('left', 'right'):
  477.             (maxw, maxh) = AD_PANEL_MAXSIZE_V
  478.             cheight = self.ClientSize.height
  479.             ad_h = min(maxh, cheight)
  480.             if ad_h < maxh:
  481.                 ad_h -= 2
  482.             
  483.             zoom = float(ad_h) / maxh
  484.             ad_w = zoom * maxw
  485.         else:
  486.             (maxw, maxh) = AD_PANEL_MAXSIZE_H
  487.             cwidth = self.ClientSize.width
  488.             ad_w = min(maxw, cwidth)
  489.             if ad_w < maxw:
  490.                 ad_w -= 2
  491.             
  492.             zoom = float(ad_w) / maxw
  493.             ad_h = zoom * maxh
  494.         ad_panel.SetMinSize((ad_w, ad_h))
  495.         ad_panel.SetPageZoom(zoom)
  496.         ad_panel.Parent.Layout()
  497.         ad_panel.Parent.Refresh()
  498.  
  499.     self.Bind(wx.EVT_SIZE, on_resize)
  500.     
  501.     def RefreshAd():
  502.         if _ad_panel_shown():
  503.             ad_panel._reload_ad()
  504.             wx.CallLater(50, on_resize)
  505.         
  506.  
  507.     rotater.on_reload += RefreshAd
  508.     ad_panel.OnDoc += on_resize
  509.     ad_panel.RefreshAd = RefreshAd
  510.     
  511.     def on_new_tab(*a):
  512.         if not getattr(self, '_first_tab_opened', False):
  513.             self._first_tab_opened = True
  514.             return None
  515.         ad_panel.RefreshAd()
  516.  
  517.     new_tab_cb += on_new_tab
  518.     self.PushEventHandler(cgui.DragMixin(self))
  519.  
  520. _cached_border_image = (None, None)
  521. _border_color = (93, 108, 122, 255)
  522.  
  523. def _get_border_image(sz):
  524.     global _cached_border_image
  525.     (w, h) = sz
  526.     sz = (w, h)
  527.     if _cached_border_image[0] == sz:
  528.         return _cached_border_image[1]
  529.     import PIL
  530.     img = PIL.Image.new('RGBA', (w, h), _border_color).WXB
  531.     _cached_border_image = (sz, img)
  532.     return img
  533.  
  534.  
  535. class Timer(object):
  536.     
  537.     def __init__(self, get_time_func = time):
  538.         self._get_time = get_time_func
  539.         self.start_ticks = 0
  540.         self.paused_ticks = 0
  541.         self.paused = False
  542.         self.started = False
  543.  
  544.     
  545.     def start(self):
  546.         self.started = True
  547.         self.paused = False
  548.         self.start_ticks = self._get_time()
  549.  
  550.     
  551.     def stop(self):
  552.         self.started = False
  553.         self.paused = False
  554.  
  555.     
  556.     def pause(self):
  557.         if not (self.started) or self.paused:
  558.             return None
  559.         self.paused = True
  560.         self.paused_ticks = self._get_time() - self.start_ticks
  561.  
  562.     
  563.     def unpause(self):
  564.         if not (self.started) or not (self.paused):
  565.             return None
  566.         self.paused = False
  567.         self.start_ticks = self._get_time() - self.paused_ticks
  568.         self.paused_ticks = 0
  569.  
  570.     
  571.     def get_ticks(self):
  572.         if not self.started:
  573.             return 0
  574.         if self.paused:
  575.             return self.paused_ticks
  576.         return self._get_time() - self.start_ticks
  577.  
  578.  
  579.  
  580. def _debug_ads():
  581.     opts = getattr(sys, 'opts', None)
  582.     return getattr(opts, 'debugads', False)
  583.  
  584.  
  585. def urls_have_same_domain(a, b):
  586.     
  587.     try:
  588.         return UrlQuery.parse(a).netloc == UrlQuery.parse(b).netloc
  589.     except Exception:
  590.         traceback.print_exc_once()
  591.         return a == b
  592.  
  593.  
  594.  
  595. def find_instances(clz):
  596.     return _[1]
  597.  
  598. last_imframe_close = None
  599.  
  600. def secs_since_last_close():
  601.     if last_imframe_close is not None:
  602.         return time() - last_imframe_close
  603.  
  604.  
  605. def should_clear_cookies():
  606.     secs = secs_since_last_close()
  607.     if secs is not None:
  608.         pass
  609.     return secs > 60 * AD_COOKIE_CLEAR_MINS
  610.  
  611.  
  612. def setup_cookie_timer(imframe):
  613.     imclz = imframe.__class__
  614.     
  615.     def num_imframes():
  616.         return len(find_instances(imclz))
  617.  
  618.     
  619.     def on_close(e):
  620.         global last_imframe_close
  621.         e.Skip()
  622.         if num_imframes() == 1:
  623.             last_imframe_close = time()
  624.         
  625.  
  626.     imframe.Bind(wx.EVT_CLOSE, on_close)
  627.     if num_imframes() == 1:
  628.         pass
  629.     return should_clear_cookies()
  630.  
  631.