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