def embedBrowser(self, url): window_info = cef.WindowInfo() # void window_info.SetAsChild(int parentWindowHandle, list windowRect), windowRect~[left,top,right,bottom] window_info.SetAsChild( int(self.winId()), [0, 0, self.width(), self.height()]) cef.PostTask(cef.TID_UI, self.create_browser, window_info, url)
def OnLoadingStateChange(self, browser, is_loading, **_): """Called when the loading state has changed.""" try: if not is_loading: # Loading is complete def yield_transforms(transforms): self.browser_context.transforms = set(transforms) def yield_rects(rects): self.browser_context.rects = rects bindings = cef.JavascriptBindings(bindToFrames=False, bindToPopups=False) bindings.SetFunction("yieldTransforms", yield_transforms) bindings.SetFunction("yieldRects", yield_rects) browser.SetJavascriptBindings(bindings) with open(self.browser_context.kle_json_file, 'r', encoding='utf-8') as f: json = f.read() browser.ExecuteJavascript(r'''(function(){ window.deserializeAndRenderAndApply(''' + json + r'''); yieldTransforms(window.retrieveTransforms()); })(); ''') cef.PostDelayedTask(cef.TID_UI, 2000, wait_retrieve_transforms, self.browser_context, browser) except: import traceback print("[kle_scraper] ERROR: Failed in OnLoadingStateChange()") traceback.print_exc() cef.PostTask(cef.TID_UI, exit_scraping, browser)
def create_browser(window, handle, alert_func): def _create(): real_url = 'data:text/html,{0}'.format( window.html ) if window.html else window.real_url or 'data:text/html,{0}'.format( default_html) default_browser_settings = {} all_browser_settings = dict(default_browser_settings, **browser_settings) cef_browser = cef.CreateBrowserSync(window_info=window_info, settings=all_browser_settings, url=real_url) browser = Browser(window, handle, cef_browser) bindings = cef.JavascriptBindings() bindings.SetObject('external', browser.js_bridge) bindings.SetFunction('alert', alert_func) cef_browser.SetJavascriptBindings(bindings) cef_browser.SetClientHandler(LoadHandler()) instances[window.uid] = browser window.events.shown.set() window_info = cef.WindowInfo() window_info.SetAsChild(handle) cef.PostTask(cef.TID_UI, _create)
def OnPaint(self, browser, element_type, dirty_rects, paint_buffer, **_): """Called when an element should be painted.""" try: if self.browser_context.capturing_screenshot and element_type == cef.PET_VIEW: if len(dirty_rects) == 0: return dr = dirty_rects[0] if dr[0] != 0 or dr[1] != 0 or dr[2] != VIEWPORT_SIZE[0] or dr[3] != VIEWPORT_SIZE[1]: # partial paint return # Buffer string is a huge string, so for performance # reasons it would be better not to copy this string. # I think that Python makes a copy of that string when # passing it to SetUserData. buffer_string = paint_buffer.GetBytes(mode="rgba", origin="top-left") # Browser object provides GetUserData/SetUserData methods # for storing custom data associated with browser. browser.SetUserData("OnPaint.buffer_string", buffer_string) self.browser_context.capturing_screenshot = False except: import traceback print("[kle_scraper] ERROR: Failed in OnPaint()") traceback.print_exc() cef.PostTask(cef.TID_UI, exit_scraping, browser)
def OnPaint(self, browser, element_type, paint_buffer, **_): """Called when an element should be painted.""" if self.OnPaint_called: sys.stdout.write(".") sys.stdout.flush() else: sys.stdout.write("[screenshot.py] OnPaint") self.OnPaint_called = True if element_type == cef.PET_VIEW: # Buffer string is a huge string, so for performance # reasons it would be better not to copy this string. # I think that Python makes a copy of that string when # passing it to SetUserData. buffer_string = paint_buffer.GetString(mode="rgba", origin="top-left") # Browser object provides GetUserData/SetUserData methods # for storing custom data associated with browser. self.count += 1 if self.count >= self.frames: cef.PostTask(cef.TID_UI, exit_app, browser) browser.SetUserData("OnPaint.buffer_string", buffer_string) print self.count save_screenshot(browser, self.count) else: raise Exception("Unsupported element_type in OnPaint")
def cookies(): while v.token is None: if browser.GetUserData('cookieManager'): browser.GetUserData("cookieManager").VisitAllCookies(v) time.sleep(1) cef.PostTask(0, lambda: cef.QuitMessageLoop())
def OnBeforePopup(self, browser, frame, targetUrl, targetFrameName, popupFeatures, windowInfo, client, browserSettings, noJavascriptAccess): print(g_ardutag + "LifespanHandler::OnBeforePopup()") print(" targetUrl = %s" % targetUrl) # Set WindowInfo object: # > windowInfo[0] = cefpython.WindowInfo() # On Windows there are keyboard problems in popups in wxPython, when # popup is created using "window.open" or "target=blank". # The solution is to create window explicitly, and not depend # on CEF to create window internally. See Issue 80 for details: # https://code.google.com/p/cefpython/issues/detail?id=80 # # If you set allowPopups=True then CEF will create popup window. # The wx.Frame cannot be created here, as this callback is executed on # the IO thread. Window should be created on the UI thread. # One solution is to call cefpython.CreateBrowser() which runs # asynchronously and can be called on any thread. # The other solution is to post a task on the UI thread, so that # cefpython.CreateBrowserSync() can be used. cefpython.PostTask(cefpython.TID_UI, self._CreatePopup, targetUrl) allowPopups = False return not allowPopups
def OnBeforePopup(self, browser, frame, targetUrl, targetFrameName, popupFeatures, windowInfo, client, browserSettings, noJavascriptAccess): # print("[wxpython.py] LifespanHandler::OnBeforePopup()") # print(" targetUrl = %s" % targetUrl) # Custom browser settings for popups: # > browserSettings[0] = {"plugins_disabled": True} # Set WindowInfo object: # > windowInfo[0] = cefpython.WindowInfo() # On Windows there are keyboard problems in popups, when popup # is created using "window.open" or "target=blank". This issue # occurs only in wxPython. PyGTK or PyQt do not require this fix. # The solution is to create window explicitilly, and not depend # on CEF to create window internally. # If you set allowPopups=True then CEF will create popup window. # The wx.Frame cannot be created here, as this callback is # executed on the IO thread. Window should be created on the UI # thread. One solution is to call cefpython.CreateBrowser() # which runs asynchronously and can be called on any thread. # The other solution is to post a task on the UI thread, so # that cefpython.CreateBrowserSync() can be used. cefpython.PostTask(cefpython.TID_UI, self._CreatePopup, targetUrl) allowPopups = False return not allowPopups
def checkAreasToUpdates(): global state, area # print "check area to update: " + state # sys.stdout.write('\n') if state == 'image saved' or state == 'page fully loaded': # global area print 'begin check area' if area: print 'delete area' area.delete() area = None area = AreaToUpdate.objects().first() if area: # area = areas[len(areas)-1] # AreaToUpdate.objects().first() # global isLoaded, x, y, width, height state = 'image loading' print "checking areas to update: post load area task" planetX = float(area.planetX) planetY = float(area.planetY) points = area.box['coordinates'][0] left = points[0][0] top = points[0][1] right = points[2][0] bottom = points[2][1] topLeft = posOnPlanetToProject(left, top, planetX, planetY) bottomRight = posOnPlanetToProject(right, bottom, planetX, planetY) cefpython.PostTask(cefpython.TID_UI, loadArea)
def create_browser(window, handle, alert_func): def _create(): real_url = 'data:text/html,{0}'.format(window.html) if window.html else window.real_url or 'data:text/html,{0}'.format(default_html) cef_browser = cef.CreateBrowserSync(window_info=window_info, url=real_url) browser = Browser(window, handle, cef_browser) bindings = cef.JavascriptBindings() bindings.SetObject('external', browser.js_bridge) bindings.SetFunction('alert', alert_func) cef_browser.SetJavascriptBindings(bindings) cef_browser.SetClientHandler(LoadHandler()) instances[window.uid] = browser window.shown.set() if window.icon: icon = window.icon+".ico" if os.path.isfile(icon): smallx = windll.user32.GetSystemMetrics(49) #SM_CXSMICON smally = windll.user32.GetSystemMetrics(50) #SM_CYSMICON small_icon = windll.user32.LoadImageW(0, icon, 1, smallx, smally, 0x00000010) windll.user32.SendMessageW(handle, 0x0080, 0, small_icon) bigx = windll.user32.GetSystemMetrics(11) #SM_CXICON bigy = windll.user32.GetSystemMetrics(12) #SM_CYICON big_icon = windll.user32.LoadImageW(0, icon, 1, bigx, bigy, 0x00000010) windll.user32.SendMessageW(handle, 0x0080, 1, big_icon) window_info = cef.WindowInfo() window_info.SetAsChild(handle) cef.PostTask(cef.TID_UI, _create)
def create_browser(uid, handle, alert_func, url=None, js_api=None, text_select=False): def _create(): real_url = url or 'data:text/html,{0}'.format(default_html) cef_browser = cef.CreateBrowserSync(window_info=window_info, url=real_url) browser = Browser(handle, cef_browser, js_api, text_select, uid) bindings = cef.JavascriptBindings() bindings.SetObject('external', browser.js_bridge) bindings.SetFunction('alert', alert_func) cef_browser.SetJavascriptBindings(bindings) cef_browser.SetClientHandler(LoadHandler()) instances[uid] = browser _webview_ready.set() window_info = cef.WindowInfo() window_info.SetAsChild(handle) cef.PostTask(cef.TID_UI, _create)
def new_task(func): """ Creates an async task (used to create browsers after starting main GUI loop) :param func: Function which contains the blueprint of a window :return: """ cef.PostTask(cef.TID_UI, func)
def OnBeforePopup(self, browser, frame, targetUrl, targetFrameName, popupFeatures, windowInfo, client, browserSettings, noJavascriptAccess): cefpython.PostTask(cefpython.TID_UI, self._CreatePopup, targetUrl) allowPopups = False return not allowPopups
def wrapped(bc: BrowserContext, browser): try: return func(bc, browser) except: import traceback print("[kle_scraper] Uncaught exception raised.") traceback.print_exc() cef.PostTask(cef.TID_UI, exit_scraping, browser)
def OnLoadingStateChange(self, browser, is_loading, **_): """Called when the loading state has changed.""" if not is_loading: # Loading is complete sys.stdout.write(os.linesep) print("[screenshot.py] Web page loading is complete") save_screenshot(browser) # See comments in exit_app() why PostTask must be used cef.PostTask(cef.TID_UI, exit_app, browser)
def OnLoadError(self, browser, frame, error_code, failed_url, **_): """Called when the resource load for a navigation fails or is canceled.""" if not frame.IsMain(): # We are interested only in loading main url. # Ignore any errors during loading of other frames. return print("[kle_scraper] ERROR: Failed to load url: {url}".format(url=failed_url)) print("[kle_scraper] Error code: {code}".format(code=error_code)) # See comments in exit_scraping() why PostTask must be used cef.PostTask(cef.TID_UI, exit_scraping, browser)
def save_screenshot(browser): # Browser object provides GetUserData/SetUserData methods # for storing custom data associated with browser. The # "OnPaint.buffer_string" data is set in RenderHandler.OnPaint. buffer_string = browser.GetUserData("OnPaint.buffer_string") if not buffer_string: raise Exception("buffer_string is empty, OnPaint never called?") image = Image.frombytes("RGBA", VIEWPORT_SIZE, buffer_string, "raw", "RGBA", 0, 1) image.save(SCREENSHOT_PATH, "PNG") print("[screenshot.py] Saved image: {path}".format(path=SCREENSHOT_PATH)) # See comments in exit_app() why PostTask must be used cef.PostTask(cef.TID_UI, exit_app, browser)
def embed_browser(self): window_info = cef.WindowInfo() rect = [0, 0, self.winfo_width(), self.winfo_height()] window_info.SetAsChild(self.get_window_handle(), rect) if g_multi_threaded: cef.PostTask(cef.TID_UI, self.create_browser, window_info, {}, "about:blank") else: self.create_browser(window_info=window_info, settings={}, url="about:blank") self.browser_setup()
def main(): command_line_args() check_versions() sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error settings = { "multi_threaded_message_loop": g_multi_threaded, } cef.Initialize(settings=settings) window_proc = { win32con.WM_CLOSE: close_window, win32con.WM_DESTROY: exit_app, win32con.WM_SIZE: WindowUtils.OnSize, win32con.WM_SETFOCUS: WindowUtils.OnSetFocus, win32con.WM_ERASEBKGND: WindowUtils.OnEraseBackground } window_handle = create_window(title="PyWin32 example", class_name="pywin32.example", width=800, height=600, window_proc=window_proc, icon="resources/chromium.ico") window_info = cef.WindowInfo() window_info.SetAsChild(window_handle) if g_multi_threaded: # When using multi-threaded message loop, CEF's UI thread # is no more application's main thread. In such case browser # must be created using cef.PostTask function and CEF message # loop must not be run explicitilly. cef.PostTask(cef.TID_UI, create_browser, window_info, {}, "https://www.google.com/") win32gui.PumpMessages() else: create_browser(window_info=window_info, settings={}, url="https://www.google.com/") cef.MessageLoop() cef.Shutdown()
def saveOnServer(imageDataURL, x, y, finished, cityPk): print 'received image to save' imageData = re.search(r'base64,(.*)', imageDataURL).group(1) try: image = Image.open(StringIO.StringIO( imageData.decode('base64'))) # Pillow version except IOError: return {'state': 'error', 'message': 'impossible to read image.'} saveImage(image, x, y, cityPk) if not finished: print 'post loopRasterize task' cefpython.PostTask(cefpython.TID_UI, loopRasterize) else: global state state = 'image saved' return
def create_browser(window, handle, alert_func): def _create(): real_url = ("data:text/html,{0}".format(window.html) if window.html else window.url or "data:text/html,{0}".format(default_html)) cef_browser = cef.CreateBrowserSync(window_info=window_info, url=real_url) browser = Browser(window, handle, cef_browser) bindings = cef.JavascriptBindings() bindings.SetObject("external", browser.js_bridge) bindings.SetFunction("alert", alert_func) cef_browser.SetJavascriptBindings(bindings) cef_browser.SetClientHandler(LoadHandler()) instances[window.uid] = browser window.shown.set() window_info = cef.WindowInfo() window_info.SetAsChild(handle) cef.PostTask(cef.TID_UI, _create)
def wait_screenshot(bc: BrowserContext, browser): if bc.capturing_screenshot: cef.PostDelayedTask(cef.TID_UI, 100, wait_screenshot, bc, browser) return buffer_string = browser.GetUserData("OnPaint.buffer_string") if not buffer_string: raise Exception("buffer_string is empty, OnPaint never called?") image = Image.frombytes("RGBA", VIEWPORT_SIZE, buffer_string, "raw", "RGBA", 0, 1) # check bottom right pixel of rendered image _, _, _, rb_pixel_a = image.getpixel((VIEWPORT_SIZE[0] - 18, VIEWPORT_SIZE[1] - 18)) if rb_pixel_a == 0: # Rendering is not completed. Capture again. bc.capturing_screenshot = True browser.Invalidate(cef.PET_VIEW) cef.PostDelayedTask(cef.TID_UI, 100, wait_screenshot, bc, browser) return # tr = bc.current_transform.replace('\n', '_') # image.save(os.path.join(bc.image_output_dir, f"full-{tr}.png")) for i, (idx, br) in enumerate(bc.rects): p = os.path.join(bc.image_output_dir, f"{str(idx)}.png") keylabel_image = image.crop([br['left'], br['top'], br['right'], br['bottom'], ]) keylabel_image.save(p) bc.shot_transforms.add(bc.current_transform) rest_trs = bc.transforms - bc.shot_transforms if len(rest_trs) > 0: bc.current_transform = next(iter(rest_trs)) exec_retrieve_rects(bc, browser) return with open(bc.kle_json_file, 'r', encoding='utf-8') as f: json = f.read() bc.kle_keyboard = kle_serial.parse(json) cef.PostTask(cef.TID_UI, exit_scraping, browser)
def OnPaint(self, browser, element_type, paint_buffer, **_): """Called when an element should be painted.""" self.frameCount = self.frameCount + 1 time = current_milli_time() fps = 1000.0 / (time - self.lastTime) self.lastTime = time sys.stdout.write( "[capture.py] frame={number: >5} fps={fps: >6.2f}\r".format( number=self.frameCount, fps=fps)) sys.stdout.flush() if element_type == cef.PET_VIEW: try: global fifo fifo.write(paint_buffer.GetString()) fifo.flush() except Exception as ex: print("[capture.py] Error {0}".format(str(ex))) # See comments in exit_app() why PostTask must be used cef.PostTask(cef.TID_UI, exit_app, browser) else: raise Exception("Unsupported element_type in OnPaint")
def save_screenshot(browser): # Browser object provides GetUserData/SetUserData methods # for storing custom data associated with browser. The # "OnPaint.buffer_string" data is set in RenderHandler.OnPaint. buffer_string = browser.GetUserData("OnPaint.buffer_string") if not buffer_string: # Sometimes LoadHandler.OnLoadingStateChange gets called # before RenderHandler.OnPaint. if not browser.GetUserData("save_screenshot.delay_printed"): sys.stdout.write("[screenshot.py] Delay") sys.stdout.flush() browser.SetUserData("save_screenshot.delay_printed", True) else: sys.stdout.write(".") sys.stdout.flush() cef.PostDelayedTask(cef.TID_UI, 13, save_screenshot, browser) return image = Image.frombytes("RGBA", VIEWPORT_SIZE, buffer_string, "raw", "RGBA", 0, 1) image.save(SCREENSHOT_PATH, "PNG") sys.stdout.write(os.linesep) print("[screenshot.py] Saved image: {path}".format(path=SCREENSHOT_PATH)) # See comments in exit_app() why PostTask must be used cef.PostTask(cef.TID_UI, exit_app, browser)
def __browserThread(self, withLoadHandler): cef.Initialize(settings=self.cefSettings) print("CEF Initialized") cef.PostTask(cef.TID_UI, self.__createBrowser, *[withLoadHandler]) print("Browser created")
def OnLoadingStateChange(self, browser, is_loading, **_): nonlocal img_path if not is_loading: save_screenshot(browser, img_path) cef.PostTask(cef.TID_UI, exit_app, browser)
def OnLoadError(self, browser, frame, error_code, failed_url, **_): if not frame.IsMain(): return cef.PostTask(cef.TID_UI, exit_app, browser)
def thread_excepthook(arg): print("Error occurring in thread:", arg.thread.name) cef.PostTask(cef.TID_UI, cef.ExceptHook, arg.exc_type, arg.exc_value, arg.exc_traceback)
def exit_gracefully(signum, frame): global browser print("") # print(os.linesep) # "[capture.py] Signal " + str(signum)) cef.PostTask(cef.TID_UI, exit_app, browser)
def __init__(self, landing_page='', start_page='', window_title=None, port_number=None, window_dimensions=(400, 300), icon_path=None, developer_mode=False): self.window_dimensions = window_dimensions self.port_number = get_open_port( ) if port_number is None else port_number self.default_text = landing_page self.window_title = window_title if window_title is not None else self.__class__.__name__ self.start_page = start_page self.javascript_bound = False self.bindings = cef.JavascriptBindings(bindToFrames=True, bindToPopups=True) self.queue = queue.Queue() self.methods = None self.isClosing = threading.Event() self._return_queue_dict = dict() self.icon_path = icon_path self.developer_mode = developer_mode check_versions() sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error cef.DpiAware.SetProcessDpiAware() # Path fix used when freezing using cx_freeze freeze_paths = { 'browser_subprocess_path': os.path.dirname(sys.executable) + r'\cefpython3\subprocess.exe', 'resources_dir_path': os.path.dirname(sys.executable) + r'\cefpython3', 'locales_dir_path': os.path.dirname(sys.executable) + r'\cefpython3\locales' } if getattr(sys, 'frozen', False) else {} if developer_mode: dev_options = { 'context_menu': { 'enabled': True }, 'debug': True, 'log_severity': 0 } else: dev_options = {'context_menu': {'enabled': False}} cef.Initialize( settings={ 'auto_zooming': 'system_dpi', 'multi_threaded_message_loop': True, **dev_options, **freeze_paths }) browser = None # Dance a little jig to do synchronous asynchronous initialisation... postqueue = queue.Queue() def create_browser(): print('Serving on localhost:' + str(self.port_number)) postqueue.put( cef.CreateBrowserSync(url=r"http://localhost:" + str(self.port_number) + '/' + self.start_page, window_title=self.window_title)) cef.PostTask(cef.TID_UI, create_browser) self.browser = postqueue.get() self.window = JSAcessObject(browser=self.browser, queue_ref=self.queue, app=self)